From 7eac3f29f51a9008aaa7721099b31b2a4fa20647 Mon Sep 17 00:00:00 2001 From: Andre Pereira <219305055+cx-andre-pereira@users.noreply.github.com> Date: Thu, 24 Jul 2025 12:23:33 +0100 Subject: [PATCH 01/13] fix(query): fn for DynamoDB Table Not Encrypted-cloudformation/aws plus complete boolean logic update --- assets/libraries/cloudformation.rego | 6 + .../query.rego | 2 +- .../test/positive3.yaml | 9 + .../test/positive_expected_result.json | 6 + .../query.rego | 6 +- .../test/negative7.yaml | 25 +++ .../test/negative8.json | 34 +++ .../test/positive5.yaml | 17 ++ .../test/positive6.json | 23 +++ .../test/positive_expected_result.json | 22 +- .../query.rego | 6 +- .../test/negative7.yaml | 25 +++ .../test/negative8.json | 34 +++ .../test/positive5.yaml | 20 ++ .../test/positive6.json | 26 +++ .../test/positive_expected_result.json | 27 ++- .../query.rego | 2 +- .../test/negative3.yaml | 31 +++ .../test/negative4.json | 43 ++++ .../test/positive5.yaml | 31 +++ .../test/positive6.json | 43 ++++ .../test/positive_expected_result.json | 12 ++ .../query.rego | 6 +- .../test/negative3.yaml | 10 + .../test/negative4.json | 18 ++ .../test/positive5.yaml | 10 + .../test/positive6.json | 18 ++ .../test/positive_expected_result.json | 22 +- .../query.rego | 2 +- .../test/negative3.yaml | 19 ++ .../test/negative4.json | 27 +++ .../test/positive5.json | 27 +++ .../test/positive6.yaml | 18 ++ .../test/positive_expected_result.json | 18 +- .../aws/api_gateway_xray_disabled/query.rego | 8 +- .../test/positive_expected_result.json | 12 +- .../query.rego | 2 +- .../test/negative1.yaml | 41 +--- .../test/negative2.json | 44 ---- .../test/negative3.yaml | 30 +++ .../test/negative4.json | 30 +++ .../test/positive1.yaml | 42 +--- .../test/positive2.json | 41 ---- .../test/positive3.yaml | 42 ++++ .../test/positive4.json | 48 +++++ .../test/positive_expected_result.json | 36 +++- .../query.rego | 2 +- .../test/negative5.json | 39 ++++ .../test/negative6.yaml | 26 +++ .../test/positive3.yaml | 25 +++ .../test/positive4.json | 39 ++++ .../test/positive_expected_result.json | 18 +- .../cdn_configuration_is_missing/query.rego | 7 +- .../query.rego | 2 +- .../test/negative2.json | 2 +- .../test/negative3.yaml | 71 +++++++ .../test/negative4.json | 110 ++++++++++ .../test/positive3.yaml | 85 ++++++++ .../test/positive4.json | 130 ++++++++++++ .../test/positive_expected_result.json | 30 ++- .../cloudtrail_logging_disabled/query.rego | 2 +- .../test/negative1.yaml | 50 ----- .../test/negative2.json | 73 ------- .../test/negative3.yaml | 21 ++ .../test/negative4.json | 37 ++++ .../test/positive1.yaml | 50 ----- .../test/positive2.json | 73 ------- .../test/positive3.yaml | 21 ++ .../test/positive4.json | 36 ++++ .../test/positive_expected_result.json | 24 ++- .../query.rego | 8 +- .../test/negative3.yaml | 70 +++++++ .../test/negative4.json | 109 ++++++++++ .../test/positive3.yaml | 70 +++++++ .../test/positive_expected_result.json | 22 +- .../cloudwatch_metrics_disabled/query.rego | 2 +- .../aws/cmk_is_unusable/query.rego | 2 +- .../aws/cmk_is_unusable/test/negative1.yaml | 1 - .../aws/cmk_is_unusable/test/negative3.yaml | 30 +++ .../aws/cmk_is_unusable/test/positive1.yaml | 1 - .../aws/cmk_is_unusable/test/positive3.yaml | 30 +++ .../test/positive_expected_result.json | 10 +- .../aws/cmk_rotation_disabled/query.rego | 6 +- .../cmk_rotation_disabled/test/negative3.yaml | 32 +++ .../cmk_rotation_disabled/test/positive3.yaml | 32 +++ .../test/positive_expected_result.json | 14 +- .../query.rego | 4 +- .../test/negative3.yaml | 24 +++ .../test/positive3.yaml | 18 ++ .../test/positive_expected_result.json | 8 +- .../query.rego | 2 +- .../test/negative5.yaml | 40 ++++ .../test/positive7.yaml | 34 +++ .../test/positive_expected_result.json | 22 +- .../aws/default_kms_key_usage/query.rego | 2 +- .../default_kms_key_usage/test/negative3.yaml | 36 ++++ .../default_kms_key_usage/test/positive3.yaml | 36 ++++ .../test/positive_expected_result.json | 6 + .../dynamodb_table_not_encrypted/query.rego | 2 +- .../test/positive3.yml | 55 +++++ .../test/positive_expected_result.json | 6 + .../query.rego | 2 +- .../test/negative3.yaml | 6 + .../test/positive7.yaml | 6 + .../test/positive_expected_result.json | 6 + .../dynamodb_with_aws_owned_cmk/query.rego | 2 +- .../test/{positive4.yaml => positive2.yaml} | 0 .../test/{positive7.json => positive4.json} | 17 +- .../test/positive5.json | 17 +- .../test/{positive8.json => positive6.json} | 0 .../test/positive7.yaml | 17 ++ .../test/positive_expected_result.json | 26 ++- .../ebs_volume_encryption_disabled/query.rego | 2 +- .../test/negative3.yaml | 13 ++ .../test/positive5.yaml | 14 ++ .../test/positive_expected_result.json | 14 +- .../query.rego | 2 +- .../test/negative2.yaml | 7 + .../test/positive3.yaml | 7 + .../test/positive_expected_result.json | 6 + .../query.rego | 2 +- .../test/negative3.yaml | 13 ++ .../test/positive3.yaml | 13 ++ .../test/positive_expected_result.json | 6 + .../aws/ec2_not_ebs_optimized/query.rego | 2 +- .../ec2_not_ebs_optimized/test/negative5.yaml | 16 ++ .../ec2_not_ebs_optimized/test/positive7.yaml | 16 ++ .../test/positive_expected_result.json | 6 + .../aws/efs_not_encrypted/query.rego | 2 +- .../aws/efs_not_encrypted/test/negative3.yaml | 108 ++++++++++ .../aws/efs_not_encrypted/test/positive3.yaml | 108 ++++++++++ .../test/positive_expected_result.json | 6 + .../aws/efs_without_kms/query.rego | 2 +- .../aws/efs_without_kms/test/negative3.yaml | 147 +++++++++++++ .../aws/efs_without_kms/test/positive3.yaml | 146 +++++++++++++ .../test/positive_expected_result.json | 6 + .../query.rego | 2 +- .../test/negative3.yaml | 30 +++ .../test/positive5.yaml | 28 +++ .../test/positive_expected_result.json | 16 +- .../query.rego | 2 +- .../test/negative3.yaml | 29 +++ .../test/positive5.yaml | 27 +++ .../test/positive_expected_result.json | 22 +- .../elasticsearch_logs_disabled/query.rego | 2 +- .../test/positive6.yaml | 48 +++++ .../test/positive_expected_result.json | 6 + .../query.rego | 2 +- .../test/negative1.yaml | 4 +- .../test/negative3.yaml | 34 +++ .../test/positive5.yaml | 35 ++++ .../test/positive_expected_result.json | 20 +- .../query.rego | 2 +- .../test/negative2.yaml | 16 ++ .../test/positive4.yaml | 16 ++ .../test/positive_expected_result.json | 6 + .../query.rego | 2 +- .../test/positive7.yaml | 40 ++++ .../test/positive_expected_result.json | 6 + .../aws/elb_access_log_disabled/query.rego | 2 +- .../test/negative3.yaml | 32 +++ .../test/positive5.yaml | 32 +++ .../test/positive_expected_result.json | 14 +- .../elb_v2_alb_access_log_disabled/query.rego | 2 +- .../test/negative3.yaml | 32 +++ .../test/positive5.yaml | 32 +++ .../test/positive_expected_result.json | 6 + .../query.rego | 6 +- .../test/negative7.yaml | 16 ++ .../test/positive9.yaml | 14 ++ .../test/positive_expected_result.json | 52 +++-- .../query.rego | 2 +- .../test/negative1.yaml | 4 +- .../test/negative3.yaml | 16 ++ .../test/positive5.yaml | 16 ++ .../test/positive_expected_result.json | 18 +- .../guardduty_detector_disabled/query.rego | 2 +- .../test/negative3.yaml | 7 + .../test/positive3.yaml | 7 + .../test/positive_expected_result.json | 6 + .../iam_database_auth_not_enabled/query.rego | 2 +- .../test/negative5.yaml | 19 ++ .../test/positive5.yaml | 20 ++ .../test/positive_expected_result.json | 10 +- .../query.rego | 3 +- .../test/negative1.yaml | 2 +- .../test/negative3.yaml | 48 +++++ .../test/positive3.yaml | 92 +++++++++ .../test/positive_expected_result.json | 26 ++- .../query.rego | 4 +- .../test/negative3.yaml | 24 +++ .../test/positive3.yaml | 24 +++ .../test/positive_expected_result.json | 6 + .../aws/mq_broker_logging_disabled/query.rego | 2 +- .../test/negative3.yaml | 27 +++ .../test/positive3.yaml | 103 ++++++++++ .../test/positive_expected_result.json | 30 +++ .../query.rego | 7 +- .../msk_cluster_logging_disabled/query.rego | 2 +- .../test/negative5.yaml | 23 +++ .../test/positive7.yaml | 26 +++ .../test/positive_expected_result.json | 72 ++++--- .../query.rego | 2 +- .../test/negative3.yaml | 8 + .../test/positive3.yaml | 13 ++ .../test/positive_expected_result.json | 30 ++- .../query.rego | 2 +- .../test/negative3.yaml | 32 +++ .../test/positive3.yaml | 32 +++ .../test/positive_expected_result.json | 14 +- .../query.rego | 2 +- .../test/negative3.yaml | 68 ++++++ .../test/positive3.yaml | 69 +++++++ .../test/positive_expected_result.json | 6 + .../query.rego | 2 +- .../test/negative3.yaml | 39 ++++ .../test/positive5.yaml | 40 ++++ .../test/positive_expected_result.json | 10 +- .../query.rego | 2 +- .../test/negative3.yaml | 194 ++++++++++++++++++ .../test/positive3.yaml | 183 +++++++++++++++++ .../test/positive_expected_result.json | 6 + .../query.rego | 2 +- .../test/negative3.yaml | 53 +++++ .../test/positive6.yaml | 54 +++++ .../test/positive_expected_result.json | 14 +- .../aws/rds_storage_not_encrypted/query.rego | 4 +- .../test/negative3.yaml | 35 ++++ .../test/positive5.yaml | 37 ++++ .../test/positive_expected_result.json | 16 +- .../aws/redshift_not_encrypted/query.rego | 2 +- .../test/negative3.yaml | 25 +++ .../test/positive5.yaml | 26 +++ .../test/positive_expected_result.json | 6 + .../redshift_publicly_accessible/query.rego | 2 +- .../test/negative3.yaml | 15 ++ .../test/positive3.yaml | 26 +++ .../test/positive_expected_result.json | 12 ++ .../s3_bucket_allows_public_acl/query.rego | 2 +- .../test/negative3.yaml | 9 + .../test/positive3.yaml | 23 +++ .../test/positive_expected_result.json | 18 ++ .../s3_bucket_with_public_policy/query.rego | 2 +- .../test/negative1.yaml | 8 +- .../test/negative3.yaml | 9 + .../test/positive3.yaml | 21 ++ .../test/positive_expected_result.json | 18 ++ .../query.rego | 2 +- .../test/negative3.yaml | 9 + .../test/positive3.yaml | 22 ++ .../test/positive_expected_result.json | 18 ++ .../query.rego | 2 +- .../test/negative3.yaml | 9 + .../test/positive3.yaml | 21 ++ .../test/positive_expected_result.json | 18 ++ .../query.rego | 15 +- .../aws/secure_ciphers_disabled/query.rego | 2 +- .../test/negative3.yaml | 25 +++ .../test/positive3.yaml | 26 +++ .../test/positive_expected_result.json | 6 + .../aws/stack_retention_disabled/query.rego | 4 +- .../test/negative3.yaml | 11 + .../test/positive3.yaml | 42 ++++ .../test/positive_expected_result.json | 30 +++ .../aws/unscanned_ecr_image/query.rego | 7 +- .../test/positive_expected_result.json | 10 +- .../query.rego | 2 +- .../test/negative1.yaml | 2 +- .../test/negative3.yaml | 25 +++ .../test/positive7.yaml | 25 +++ .../test/positive_expected_result.json | 10 +- .../query.rego | 8 +- .../test/{positive3.yaml => positive1.yaml} | 2 +- .../test/positive2.yaml | 2 +- .../test/{positive5.json => positive3.json} | 0 .../test/{positive6.json => positive4.json} | 0 .../test/positive_expected_result.json | 18 +- .../workspace_without_encryption/query.rego | 9 +- .../test/positive_expected_result.json | 14 +- 279 files changed, 5583 insertions(+), 782 deletions(-) create mode 100644 assets/queries/cloudFormation/aws/amazon_dms_replication_instance_is_publicly_accessible/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/negative7.yaml create mode 100644 assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/negative8.json create mode 100644 assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive5.yaml create mode 100644 assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive6.json create mode 100644 assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/negative7.yaml create mode 100644 assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/negative8.json create mode 100644 assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/positive5.yaml create mode 100644 assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/positive6.json create mode 100644 assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/test/negative4.json create mode 100644 assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/test/positive5.yaml create mode 100644 assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/test/positive6.json create mode 100644 assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/test/negative4.json create mode 100644 assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/test/positive5.yaml create mode 100644 assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/test/positive6.json create mode 100644 assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/test/negative4.json create mode 100644 assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/test/positive5.json create mode 100644 assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/test/positive6.yaml create mode 100644 assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/negative4.json create mode 100644 assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/positive4.json create mode 100644 assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/test/negative5.json create mode 100644 assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/test/negative6.yaml create mode 100644 assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/test/positive4.json create mode 100644 assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/negative4.json create mode 100644 assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/positive4.json create mode 100644 assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/negative4.json create mode 100644 assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/positive4.json create mode 100644 assets/queries/cloudFormation/aws/cloudtrail_multi_region_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/cloudtrail_multi_region_disabled/test/negative4.json create mode 100644 assets/queries/cloudFormation/aws/cloudtrail_multi_region_disabled/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/cmk_is_unusable/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/cmk_is_unusable/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/cmk_rotation_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/cmk_rotation_disabled/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/config_configuration_aggregator_to_all_regions_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/config_configuration_aggregator_to_all_regions_disabled/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/db_security_group_with_public_scope/test/negative5.yaml create mode 100644 assets/queries/cloudFormation/aws/db_security_group_with_public_scope/test/positive7.yaml create mode 100644 assets/queries/cloudFormation/aws/default_kms_key_usage/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/default_kms_key_usage/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/dynamodb_table_not_encrypted/test/positive3.yml create mode 100644 assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive7.yaml rename assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/{positive4.yaml => positive2.yaml} (100%) rename assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/{positive7.json => positive4.json} (71%) rename assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/{positive8.json => positive6.json} (100%) create mode 100644 assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive7.yaml create mode 100644 assets/queries/cloudFormation/aws/ebs_volume_encryption_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/ebs_volume_encryption_disabled/test/positive5.yaml create mode 100644 assets/queries/cloudFormation/aws/ec2_instance_monitoring_disabled/test/negative2.yaml create mode 100644 assets/queries/cloudFormation/aws/ec2_instance_monitoring_disabled/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/ec2_instance_subnet_has_public_ip_mapping_on_launch/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/ec2_instance_subnet_has_public_ip_mapping_on_launch/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/ec2_not_ebs_optimized/test/negative5.yaml create mode 100644 assets/queries/cloudFormation/aws/ec2_not_ebs_optimized/test/positive7.yaml create mode 100644 assets/queries/cloudFormation/aws/efs_not_encrypted/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/efs_not_encrypted/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/efs_without_kms/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/efs_without_kms/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/elasticache_with_disabled_at_rest_encryption/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/elasticache_with_disabled_at_rest_encryption/test/positive5.yaml create mode 100644 assets/queries/cloudFormation/aws/elasticache_with_disabled_transit_encryption/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/elasticache_with_disabled_transit_encryption/test/positive5.yaml create mode 100644 assets/queries/cloudFormation/aws/elasticsearch_logs_disabled/test/positive6.yaml create mode 100644 assets/queries/cloudFormation/aws/elasticsearch_not_encrypted_at_rest/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/elasticsearch_not_encrypted_at_rest/test/positive5.yaml create mode 100644 assets/queries/cloudFormation/aws/elasticsearch_with_https_disabled/test/negative2.yaml create mode 100644 assets/queries/cloudFormation/aws/elasticsearch_with_https_disabled/test/positive4.yaml create mode 100644 assets/queries/cloudFormation/aws/elasticsearch_without_slow_logs/test/positive7.yaml create mode 100644 assets/queries/cloudFormation/aws/elb_access_log_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/elb_access_log_disabled/test/positive5.yaml create mode 100644 assets/queries/cloudFormation/aws/elb_v2_alb_access_log_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/elb_v2_alb_access_log_disabled/test/positive5.yaml create mode 100644 assets/queries/cloudFormation/aws/emr_security_configuration_encryptions_enabled/test/negative7.yaml create mode 100644 assets/queries/cloudFormation/aws/emr_security_configuration_encryptions_enabled/test/positive9.yaml create mode 100644 assets/queries/cloudFormation/aws/github_repository_set_to_public/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/github_repository_set_to_public/test/positive5.yaml create mode 100644 assets/queries/cloudFormation/aws/guardduty_detector_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/guardduty_detector_disabled/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_database_auth_not_enabled/test/negative5.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_database_auth_not_enabled/test/positive5.yaml create mode 100644 assets/queries/cloudFormation/aws/kms_enable_key_rotation_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/kms_enable_key_rotation_disabled/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/mq_broker_is_publicly_accessible/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/mq_broker_is_publicly_accessible/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/mq_broker_logging_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/mq_broker_logging_disabled/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/msk_cluster_logging_disabled/test/negative5.yaml create mode 100644 assets/queries/cloudFormation/aws/msk_cluster_logging_disabled/test/positive7.yaml create mode 100644 assets/queries/cloudFormation/aws/neptune_cluster_with_iam_database_authentication_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/neptune_cluster_with_iam_database_authentication_disabled/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/neptune_database_cluster_encryption_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/neptune_database_cluster_encryption_disabled/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/rds_db_instance_publicly_accessible/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/rds_db_instance_publicly_accessible/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/rds_db_instance_with_deletion_protection_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/rds_db_instance_with_deletion_protection_disabled/test/positive5.yaml create mode 100644 assets/queries/cloudFormation/aws/rds_multi_az_deployment_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/rds_multi_az_deployment_disabled/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/rds_storage_encryption_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/rds_storage_encryption_disabled/test/positive6.yaml create mode 100644 assets/queries/cloudFormation/aws/rds_storage_not_encrypted/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/rds_storage_not_encrypted/test/positive5.yaml create mode 100644 assets/queries/cloudFormation/aws/redshift_not_encrypted/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/redshift_not_encrypted/test/positive5.yaml create mode 100644 assets/queries/cloudFormation/aws/redshift_publicly_accessible/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/redshift_publicly_accessible/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/s3_bucket_allows_public_acl/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/s3_bucket_allows_public_acl/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/s3_bucket_with_public_policy/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/s3_bucket_with_public_policy/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/s3_bucket_without_ignore_public_acl/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/s3_bucket_without_ignore_public_acl/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/s3_bucket_without_restriction_of_public_bucket/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/s3_bucket_without_restriction_of_public_bucket/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/secure_ciphers_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/secure_ciphers_disabled/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/stack_retention_disabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/stack_retention_disabled/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/user_iam_missing_password_reset_required/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/user_iam_missing_password_reset_required/test/positive7.yaml rename assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/{positive3.yaml => positive1.yaml} (58%) rename assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/{positive5.json => positive3.json} (100%) rename assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/{positive6.json => positive4.json} (100%) diff --git a/assets/libraries/cloudformation.rego b/assets/libraries/cloudformation.rego index bdd6e6541c7..8d4ec19eec3 100644 --- a/assets/libraries/cloudformation.rego +++ b/assets/libraries/cloudformation.rego @@ -10,6 +10,12 @@ isCloudFormationFalse(answer) { answer == false } +isCloudFormationTrue(answer) { + lower(answer) == "true" +} else { + answer == true +} + # Find out if the document has a resource type equals to 'AWS::SecretsManager::Secret' hasSecretManager(str, document) { selectedSecret := strings.replace_n({"${": "", "}": ""}, regex.find_n(`\${\w+}`, str, 1)[0]) diff --git a/assets/queries/cloudFormation/aws/amazon_dms_replication_instance_is_publicly_accessible/query.rego b/assets/queries/cloudFormation/aws/amazon_dms_replication_instance_is_publicly_accessible/query.rego index 0e56d8ec24b..c8399588ce8 100644 --- a/assets/queries/cloudFormation/aws/amazon_dms_replication_instance_is_publicly_accessible/query.rego +++ b/assets/queries/cloudFormation/aws/amazon_dms_replication_instance_is_publicly_accessible/query.rego @@ -8,7 +8,7 @@ CxPolicy[result] { resource = document[i].Resources[name] resource.Type == "AWS::DMS::ReplicationInstance" properties := resource.Properties - properties.PubliclyAccessible == true + cf_lib.isCloudFormationTrue(properties.PubliclyAccessible) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/amazon_dms_replication_instance_is_publicly_accessible/test/positive3.yaml b/assets/queries/cloudFormation/aws/amazon_dms_replication_instance_is_publicly_accessible/test/positive3.yaml new file mode 100644 index 00000000000..79579e4646d --- /dev/null +++ b/assets/queries/cloudFormation/aws/amazon_dms_replication_instance_is_publicly_accessible/test/positive3.yaml @@ -0,0 +1,9 @@ +Resources: + ReplicationInstance: + Type: "AWS::DMS::ReplicationInstance" + Properties: + ReplicationInstanceIdentifier: my-replication-instance + ReplicationInstanceClass: dms.r5.large + AllocatedStorage: 100 + EngineVersion: "3.4.3" + PubliclyAccessible: "true" diff --git a/assets/queries/cloudFormation/aws/amazon_dms_replication_instance_is_publicly_accessible/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/amazon_dms_replication_instance_is_publicly_accessible/test/positive_expected_result.json index 9cd21fa1c91..b6f9e0c14ad 100644 --- a/assets/queries/cloudFormation/aws/amazon_dms_replication_instance_is_publicly_accessible/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/amazon_dms_replication_instance_is_publicly_accessible/test/positive_expected_result.json @@ -10,5 +10,11 @@ "severity": "CRITICAL", "line": 4, "fileName": "positive2.yaml" + }, + { + "queryName": "Amazon DMS Replication Instance Is Publicly Accessible", + "severity": "CRITICAL", + "line": 9, + "fileName": "positive3.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/query.rego b/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/query.rego index 720289023c5..ba47931720c 100644 --- a/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/query.rego +++ b/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/query.rego @@ -9,7 +9,7 @@ CxPolicy[result] { resource.Type == "AWS::Amplify::App" properties := resource.Properties - properties.BasicAuthConfig.EnableBasicAuth == true + cf_lib.isCloudFormationTrue(properties.BasicAuthConfig.EnableBasicAuth) paramName := properties.BasicAuthConfig.Password defaultToken := document.Parameters[paramName].Default @@ -34,7 +34,7 @@ CxPolicy[result] { resource.Type == "AWS::Amplify::App" properties := resource.Properties - properties.BasicAuthConfig.EnableBasicAuth == true + cf_lib.isCloudFormationTrue(properties.BasicAuthConfig.EnableBasicAuth) paramName := properties.BasicAuthConfig.Password common_lib.valid_key(document, "Parameters") not common_lib.valid_key(document.Parameters, paramName) @@ -61,7 +61,7 @@ CxPolicy[result] { resource.Type == "AWS::Amplify::App" properties := resource.Properties - properties.BasicAuthConfig.EnableBasicAuth == true + cf_lib.isCloudFormationTrue(properties.BasicAuthConfig.EnableBasicAuth) paramName := properties.BasicAuthConfig.Password not common_lib.valid_key(document, "Parameters") diff --git a/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/negative7.yaml b/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/negative7.yaml new file mode 100644 index 00000000000..58c484fc2ff --- /dev/null +++ b/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/negative7.yaml @@ -0,0 +1,25 @@ +Resources: + NewAmpApp-2: + Type: AWS::Amplify::App + Properties: + BuildSpec: String + CustomHeaders: String + Description: String + EnableBranchAutoDeletion: true + IAMServiceRole: String + Name: NewAmpApp + OauthToken: String + Repository: String + BasicAuthConfig : + EnableBasicAuth: "true" + Password: !Sub '{{resolve:secretsmanager:${MyAmpAppSecretManagerRotater}::password}}' + Username: !Sub '{{resolve:secretsmanager:${MyAmpAppSecretManagerRotater}::username}}' + MyAmpAppSecretManagerRotater: + Type: AWS::SecretsManager::Secret + Properties: + Description: 'This is my amp app instance secret' + GenerateSecretString: + SecretStringTemplate: '{"username": "admin"}' + GenerateStringKey: 'password' + PasswordLength: 16 + ExcludeCharacters: '"@/\' diff --git a/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/negative8.json b/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/negative8.json new file mode 100644 index 00000000000..bfb001a447a --- /dev/null +++ b/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/negative8.json @@ -0,0 +1,34 @@ +{ + "Resources": { + "MyAmpAppSecretManagerRotater": { + "Type": "AWS::SecretsManager::Secret", + "Properties": { + "GenerateSecretString": { + "PasswordLength": 16, + "ExcludeCharacters": "\"@/\\", + "SecretStringTemplate": "{\"username\": \"admin\"}", + "GenerateStringKey": "password" + }, + "Description": "This is my amp app instance secret" + } + }, + "NewAmpApp-2": { + "Type": "AWS::Amplify::App", + "Properties": { + "BasicAuthConfig": { + "EnableBasicAuth": "true", + "Password": "{{resolve:secretsmanager:${MyAmpAppSecretManagerRotater}::password}}", + "Username": "{{resolve:secretsmanager:${MyAmpAppSecretManagerRotater}::username}}" + }, + "Description": "String", + "EnableBranchAutoDeletion": true, + "IAMServiceRole": "String", + "Name": "NewAmpApp", + "BuildSpec": "String", + "CustomHeaders": "String", + "OauthToken": "String", + "Repository": "String" + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive5.yaml b/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive5.yaml new file mode 100644 index 00000000000..0cbfa83faf9 --- /dev/null +++ b/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive5.yaml @@ -0,0 +1,17 @@ +AWSTemplateFormatVersion: 2010-09-09 +Resources: + NewAmpApp-1: + Type: AWS::Amplify::App + Properties: + BuildSpec: String + CustomHeaders: String + Description: String + EnableBranchAutoDeletion: true + IAMServiceRole: String + Name: NewAmpApp + OauthToken: String + Repository: String + BasicAuthConfig: + EnableBasicAuth: "true" + Password: "@skdsjdk0234!AB" + Username: admin diff --git a/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive6.json b/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive6.json new file mode 100644 index 00000000000..bd6b9260442 --- /dev/null +++ b/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive6.json @@ -0,0 +1,23 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z", + "Resources": { + "NewAmpApp-1": { + "Type": "AWS::Amplify::App", + "Properties": { + "OauthToken": "String", + "Repository": "String", + "BasicAuthConfig": { + "Username": "admin", + "EnableBasicAuth": "true", + "Password": "@skdsjdk0234!AB" + }, + "CustomHeaders": "String", + "Description": "String", + "Name": "NewAmpApp", + "BuildSpec": "String", + "EnableBranchAutoDeletion": true, + "IAMServiceRole": "String" + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive_expected_result.json index 9cb64105d2b..8d609ba8ecb 100644 --- a/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive_expected_result.json @@ -2,14 +2,14 @@ { "queryName": "Amplify App Basic Auth Config Password Exposed", "severity": "HIGH", - "line": 6, - "fileName": "positive2.yaml" + "line": 16, + "fileName": "positive1.yaml" }, { - "line": 16, - "fileName": "positive1.yaml", "queryName": "Amplify App Basic Auth Config Password Exposed", - "severity": "HIGH" + "severity": "HIGH", + "line": 6, + "fileName": "positive2.yaml" }, { "queryName": "Amplify App Basic Auth Config Password Exposed", @@ -22,5 +22,17 @@ "severity": "HIGH", "line": 12, "fileName": "positive4.json" + }, + { + "queryName": "Amplify App Basic Auth Config Password Exposed", + "severity": "HIGH", + "line": 16, + "fileName": "positive5.yaml" + }, + { + "queryName": "Amplify App Basic Auth Config Password Exposed", + "severity": "HIGH", + "line": 12, + "fileName": "positive6.json" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/query.rego b/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/query.rego index d572cb6f2ff..e28d16588da 100644 --- a/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/query.rego +++ b/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/query.rego @@ -10,7 +10,7 @@ CxPolicy[result] { resource.Type == "AWS::Amplify::Branch" properties := resource.Properties - properties.BasicAuthConfig.EnableBasicAuth == true + cf_lib.isCloudFormationTrue(properties.BasicAuthConfig.EnableBasicAuth) paramName := properties.BasicAuthConfig.Password defaultToken := document.Parameters[paramName].Default @@ -35,7 +35,7 @@ CxPolicy[result] { resource.Type == "AWS::Amplify::Branch" properties := resource.Properties - properties.BasicAuthConfig.EnableBasicAuth == true + cf_lib.isCloudFormationTrue(properties.BasicAuthConfig.EnableBasicAuth) paramName := properties.BasicAuthConfig.Password common_lib.valid_key(document, "Parameters") not common_lib.valid_key(document.Parameters, paramName) @@ -61,7 +61,7 @@ CxPolicy[result] { resource.Type == "AWS::Amplify::Branch" properties := resource.Properties - properties.BasicAuthConfig.EnableBasicAuth == true + cf_lib.isCloudFormationTrue(properties.BasicAuthConfig.EnableBasicAuth) paramName := properties.BasicAuthConfig.Password not common_lib.valid_key(document, "Parameters") diff --git a/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/negative7.yaml b/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/negative7.yaml new file mode 100644 index 00000000000..290af9e97f7 --- /dev/null +++ b/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/negative7.yaml @@ -0,0 +1,25 @@ +Resources: + NewAmpApp: + Type: AWS::Amplify::App + Properties: + BuildSpec: String + CustomHeaders: String + Description: String + EnableBranchAutoDeletion: true + IAMServiceRole: String + Name: NewAmpApp + OauthToken: String + Repository: String + BasicAuthConfig : + EnableBasicAuth: "true" + Password: !Sub '{{resolve:secretsmanager:${MyAmpAppSecretManagerRotater}::password}}' + Username: !Sub '{{resolve:secretsmanager:${MyAmpAppSecretManagerRotater}::username}}' + MyAmpAppSecretManagerRotater: + Type: AWS::SecretsManager::Secret + Properties: + Description: 'This is my amp app instance secret' + GenerateSecretString: + SecretStringTemplate: '{"username": "admin"}' + GenerateStringKey: 'password' + PasswordLength: 16 + ExcludeCharacters: '"@/\' diff --git a/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/negative8.json b/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/negative8.json new file mode 100644 index 00000000000..24c24b214c8 --- /dev/null +++ b/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/negative8.json @@ -0,0 +1,34 @@ +{ + "Resources": { + "NewAmpApp": { + "Type": "AWS::Amplify::App", + "Properties": { + "EnableBranchAutoDeletion": true, + "IAMServiceRole": "String", + "Name": "NewAmpApp", + "OauthToken": "String", + "Repository": "String", + "BasicAuthConfig": { + "EnableBasicAuth": "true", + "Password": "{{resolve:secretsmanager:${MyAmpAppSecretManagerRotater}::password}}", + "Username": "{{resolve:secretsmanager:${MyAmpAppSecretManagerRotater}::username}}" + }, + "BuildSpec": "String", + "CustomHeaders": "String", + "Description": "String" + } + }, + "MyAmpAppSecretManagerRotater": { + "Type": "AWS::SecretsManager::Secret", + "Properties": { + "Description": "This is my amp app instance secret", + "GenerateSecretString": { + "SecretStringTemplate": "{\"username\": \"admin\"}", + "GenerateStringKey": "password", + "PasswordLength": 16, + "ExcludeCharacters": "\"@/\\" + } + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/positive5.yaml b/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/positive5.yaml new file mode 100644 index 00000000000..ff1c2f0e363 --- /dev/null +++ b/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/positive5.yaml @@ -0,0 +1,20 @@ +Resources: + NewAmpApp1: + Type: AWS::Amplify::Branch + Properties: + AppId: String + BranchName: String + BuildSpec: String + Description: String + EnableAutoBuild: false + EnablePerformanceMode: false + EnablePullRequestPreview: false + EnvironmentVariables: + - EnvironmentVariable + PullRequestEnvironmentName: String + Stage: String + BasicAuthConfig: + EnableBasicAuth: "true" + Password: "@skdsjdk0234!AB" + Username: admin + diff --git a/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/positive6.json b/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/positive6.json new file mode 100644 index 00000000000..793732c0708 --- /dev/null +++ b/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/positive6.json @@ -0,0 +1,26 @@ +{ + "Resources": { + "NewAmpApp1": { + "Type": "AWS::Amplify::Branch", + "Properties": { + "BranchName": "String", + "EnableAutoBuild": false, + "EnvironmentVariables": [ + "EnvironmentVariable" + ], + "PullRequestEnvironmentName": "String", + "AppId": "String", + "Description": "String", + "EnablePerformanceMode": false, + "EnablePullRequestPreview": false, + "Stage": "String", + "BasicAuthConfig": { + "EnableBasicAuth": "true", + "Password": "@skdsjdk0234!AB", + "Username": "admin" + }, + "BuildSpec": "String" + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/positive_expected_result.json index cf0cb7cc13a..d6968d166f3 100644 --- a/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/positive_expected_result.json @@ -2,25 +2,38 @@ { "queryName": "Amplify Branch Basic Auth Config Password Exposed", "severity": "HIGH", - "line": 5, - "fileName": "positive2.yaml" + "line": 18, + "fileName": "positive1.yaml" }, { + "queryName": "Amplify Branch Basic Auth Config Password Exposed", "severity": "HIGH", - "line": 18, - "fileName": "positive1.yaml", - "queryName": "Amplify Branch Basic Auth Config Password Exposed" + "line": 5, + "fileName": "positive2.yaml" }, { - "fileName": "positive3.json", + "queryName": "Amplify Branch Basic Auth Config Password Exposed", "severity": "HIGH", - "line": 19 + "line": 19, + "fileName": "positive3.json" }, { "queryName": "Amplify Branch Basic Auth Config Password Exposed", "severity": "HIGH", "line": 35, "fileName": "positive4.json" + }, + { + "queryName": "Amplify Branch Basic Auth Config Password Exposed", + "severity": "HIGH", + "line": 18, + "fileName": "positive5.yaml" + }, + { + "queryName": "Amplify Branch Basic Auth Config Password Exposed", + "severity": "HIGH", + "line": 19, + "fileName": "positive6.json" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/query.rego b/assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/query.rego index 69e9ba6a6cf..b682bc57226 100644 --- a/assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/query.rego @@ -28,7 +28,7 @@ CxPolicy[result] { resource.Type == "AWS::ApiGateway::Stage" properties := resource.Properties - properties.CacheClusterEnabled == false + cf_lib.isCloudFormationFalse(properties.CacheClusterEnabled) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/test/negative3.yaml new file mode 100644 index 00000000000..aabaa566c10 --- /dev/null +++ b/assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/test/negative3.yaml @@ -0,0 +1,31 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "BatchJobDefinition" +Resources: + ProdNeg1: + Type: AWS::ApiGateway::Stage + Properties: + StageName: Prod + Description: Prod Stage + RestApiId: !Ref MyRestApi + DeploymentId: !Ref TestDeployment + DocumentationVersion: !Ref MyDocumentationVersion + ClientCertificateId: !Ref ClientCertificate + TracingEnabled: true + Variables: + Stack: Prod + MethodSettings: + - ResourcePath: / + HttpMethod: GET + MetricsEnabled: 'true' + DataTraceEnabled: 'false' + - ResourcePath: /stack + HttpMethod: POST + MetricsEnabled: 'true' + DataTraceEnabled: 'false' + ThrottlingBurstLimit: '999' + - ResourcePath: /stack + HttpMethod: GET + MetricsEnabled: 'true' + DataTraceEnabled: 'false' + ThrottlingBurstLimit: '555' + CacheClusterEnabled: "true" diff --git a/assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/test/negative4.json b/assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/test/negative4.json new file mode 100644 index 00000000000..a5e2332b779 --- /dev/null +++ b/assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/test/negative4.json @@ -0,0 +1,43 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "ProdNeg1": { + "Properties": { + "CacheClusterEnabled": "true", + "ClientCertificateId": "ClientCertificate", + "DeploymentId": "TestDeployment", + "Description": "Prod Stage", + "DocumentationVersion": "MyDocumentationVersion", + "MethodSettings": [ + { + "DataTraceEnabled": "false", + "HttpMethod": "GET", + "MetricsEnabled": "true", + "ResourcePath": "/" + }, + { + "DataTraceEnabled": "false", + "HttpMethod": "POST", + "MetricsEnabled": "true", + "ResourcePath": "/stack", + "ThrottlingBurstLimit": "999" + }, + { + "DataTraceEnabled": "false", + "HttpMethod": "GET", + "MetricsEnabled": "true", + "ResourcePath": "/stack", + "ThrottlingBurstLimit": "555" + } + ], + "RestApiId": "MyRestApi", + "StageName": "Prod", + "TracingEnabled": true, + "Variables": { + "Stack": "Prod" + } + }, + "Type": "AWS::ApiGateway::Stage" + } + } +} diff --git a/assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/test/positive5.yaml b/assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/test/positive5.yaml new file mode 100644 index 00000000000..efabff0ebd1 --- /dev/null +++ b/assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/test/positive5.yaml @@ -0,0 +1,31 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "BatchJobDefinition" +Resources: + ProdPos2: + Type: AWS::ApiGateway::Stage + Properties: + StageName: Prod + Description: Prod Stage + RestApiId: !Ref MyRestApi + DeploymentId: !Ref TestDeployment + DocumentationVersion: !Ref MyDocumentationVersion + ClientCertificateId: !Ref ClientCertificate + TracingEnabled: true + Variables: + Stack: Prod + MethodSettings: + - ResourcePath: / + HttpMethod: GET + MetricsEnabled: 'true' + DataTraceEnabled: 'false' + - ResourcePath: /stack + HttpMethod: POST + MetricsEnabled: 'true' + DataTraceEnabled: 'false' + ThrottlingBurstLimit: '999' + - ResourcePath: /stack + HttpMethod: GET + MetricsEnabled: 'true' + DataTraceEnabled: 'false' + ThrottlingBurstLimit: '555' + CacheClusterEnabled: "false" diff --git a/assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/test/positive6.json b/assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/test/positive6.json new file mode 100644 index 00000000000..4ebf05354ea --- /dev/null +++ b/assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/test/positive6.json @@ -0,0 +1,43 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "ProdPos2": { + "Properties": { + "CacheClusterEnabled": "false", + "ClientCertificateId": "ClientCertificate", + "DeploymentId": "TestDeployment", + "Description": "Prod Stage", + "DocumentationVersion": "MyDocumentationVersion", + "MethodSettings": [ + { + "DataTraceEnabled": "false", + "HttpMethod": "GET", + "MetricsEnabled": "true", + "ResourcePath": "/" + }, + { + "DataTraceEnabled": "false", + "HttpMethod": "POST", + "MetricsEnabled": "true", + "ResourcePath": "/stack", + "ThrottlingBurstLimit": "999" + }, + { + "DataTraceEnabled": "false", + "HttpMethod": "GET", + "MetricsEnabled": "true", + "ResourcePath": "/stack", + "ThrottlingBurstLimit": "555" + } + ], + "RestApiId": "MyRestApi", + "StageName": "Prod", + "TracingEnabled": true, + "Variables": { + "Stack": "Prod" + } + }, + "Type": "AWS::ApiGateway::Stage" + } + } +} diff --git a/assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/test/positive_expected_result.json index 7c4344505c6..5c7f7c57d03 100644 --- a/assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/api_gateway_cache_cluster_disabled/test/positive_expected_result.json @@ -22,5 +22,17 @@ "severity": "LOW", "line": 6, "fileName": "positive4.json" + }, + { + "queryName": "API Gateway Cache Cluster Disabled", + "severity": "LOW", + "line": 31, + "fileName": "positive5.yaml" + }, + { + "queryName": "API Gateway Cache Cluster Disabled", + "severity": "LOW", + "line": 6, + "fileName": "positive6.json" } ] diff --git a/assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/query.rego b/assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/query.rego index ec28d2d6949..dab8178effa 100644 --- a/assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/query.rego @@ -10,7 +10,7 @@ CxPolicy[result] { not common_lib.valid_key(stageDescription, "CacheDataEncrypted") - stageDescription.CachingEnabled == true + cf_lib.isCloudFormationTrue(stageDescription.CachingEnabled) result := { "documentId": input.document[i].id, @@ -28,9 +28,9 @@ CxPolicy[result] { deployment.Type == "AWS::ApiGateway::Deployment" stageDescription := deployment.Properties.StageDescription - stageDescription.CacheDataEncrypted == false + cf_lib.isCloudFormationFalse(stageDescription.CacheDataEncrypted) - stageDescription.CachingEnabled == true + cf_lib.isCloudFormationTrue(stageDescription.CachingEnabled) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/test/negative3.yaml new file mode 100644 index 00000000000..19ee1ffdc71 --- /dev/null +++ b/assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/test/negative3.yaml @@ -0,0 +1,10 @@ +Resources: + Deployment: + Type: 'AWS::ApiGateway::Deployment' + Properties: + RestApiId: !Ref MyApi + Description: My deployment + StageName: DummyStage + StageDescription: + CacheDataEncrypted: "true" + CachingEnabled: "true" diff --git a/assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/test/negative4.json b/assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/test/negative4.json new file mode 100644 index 00000000000..b8e5e46c9c1 --- /dev/null +++ b/assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/test/negative4.json @@ -0,0 +1,18 @@ +{ + "Resources": { + "Deployment": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "MyApi" + }, + "Description": "My deployment", + "StageName": "DummyStage", + "StageDescription": { + "CacheDataEncrypted": "true", + "CachingEnabled": "true" + } + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/test/positive5.yaml b/assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/test/positive5.yaml new file mode 100644 index 00000000000..53cdf92cef0 --- /dev/null +++ b/assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/test/positive5.yaml @@ -0,0 +1,10 @@ +Resources: + Deployment: + Type: 'AWS::ApiGateway::Deployment' + Properties: + RestApiId: !Ref MyApi + Description: My deployment + StageName: DummyStage + StageDescription: + CacheDataEncrypted: "false" + CachingEnabled: "true" diff --git a/assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/test/positive6.json b/assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/test/positive6.json new file mode 100644 index 00000000000..d17ddd87d64 --- /dev/null +++ b/assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/test/positive6.json @@ -0,0 +1,18 @@ +{ + "Resources": { + "Deployment": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "MyApi" + }, + "Description": "My deployment", + "StageName": "DummyStage", + "StageDescription": { + "CacheDataEncrypted": "false", + "CachingEnabled": "true" + } + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/test/positive_expected_result.json index 45fb5f331e3..fc1ce51db13 100644 --- a/assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/api_gateway_cache_encrypted_disabled/test/positive_expected_result.json @@ -5,6 +5,12 @@ "severity": "HIGH", "line": 8 }, + { + "fileName": "positive2.json", + "queryName": "API Gateway Cache Encrypted Disabled", + "severity": "HIGH", + "line": 11 + }, { "fileName": "positive3.yaml", "queryName": "API Gateway Cache Encrypted Disabled", @@ -12,15 +18,21 @@ "line": 9 }, { + "fileName": "positive4.json", "queryName": "API Gateway Cache Encrypted Disabled", "severity": "HIGH", - "line": 11, - "fileName": "positive2.json" + "line": 12 }, { - "line": 12, - "fileName": "positive4.json", + "fileName": "positive5.yaml", "queryName": "API Gateway Cache Encrypted Disabled", - "severity": "HIGH" + "severity": "HIGH", + "line": 9 + }, + { + "fileName": "positive6.json", + "queryName": "API Gateway Cache Encrypted Disabled", + "severity": "HIGH", + "line": 12 } ] diff --git a/assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/query.rego b/assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/query.rego index 5360095aecf..ccf319efb09 100644 --- a/assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/query.rego +++ b/assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/query.rego @@ -26,7 +26,7 @@ CxPolicy[result] { resource = document.Resources[name] resource.Type == "AWS::ApiGateway::Method" - resource.Properties.ApiKeyRequired == false + cf_lib.isCloudFormationFalse(resource.Properties.ApiKeyRequired) result := { "documentId": document.id, diff --git a/assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/test/negative3.yaml b/assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/test/negative3.yaml new file mode 100644 index 00000000000..7d28218d6a1 --- /dev/null +++ b/assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/test/negative3.yaml @@ -0,0 +1,19 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: ApiGateway +Resources: + MockMethod: + Type: 'AWS::ApiGateway::Method' + Properties: + ApiKeyRequired: "true" + RestApiId: !Ref MyApi + ResourceId: !GetAtt + - MyApi + - RootResourceId + HttpMethod: "" + AuthorizationType: NONE + Integration: + Type: MOCK + MethodResponses: + - StatusCode : "200" + + diff --git a/assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/test/negative4.json b/assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/test/negative4.json new file mode 100644 index 00000000000..82d579c25b2 --- /dev/null +++ b/assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/test/negative4.json @@ -0,0 +1,27 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "ApiGateway", + "Resources": { + "MockMethod": { + "Type": "AWS::ApiGateway::Method", + "Properties": { + "Integration": { + "Type": "MOCK" + }, + "MethodResponses": [ + { + "StatusCode": "200" + } + ], + "ApiKeyRequired": "true", + "RestApiId": "MyApi", + "ResourceId": [ + "MyApi", + "RootResourceId" + ], + "HttpMethod": "", + "AuthorizationType": "NONE" + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/test/positive5.json b/assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/test/positive5.json new file mode 100644 index 00000000000..28b78a6bfec --- /dev/null +++ b/assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/test/positive5.json @@ -0,0 +1,27 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "ApiGateway", + "Resources": { + "MockMethod": { + "Type": "AWS::ApiGateway::Method", + "Properties": { + "MethodResponses": [ + { + "StatusCode": "200" + } + ], + "ApiKeyRequired": "false", + "RestApiId": "MyApi", + "ResourceId": [ + "MyApi", + "RootResourceId" + ], + "HttpMethod": "GET", + "AuthorizationType": "NONE", + "Integration": { + "Type": "MOCK" + } + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/test/positive6.yaml b/assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/test/positive6.yaml new file mode 100644 index 00000000000..278c82f1edf --- /dev/null +++ b/assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/test/positive6.yaml @@ -0,0 +1,18 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: ApiGateway +Resources: + MockMethod: + Type: 'AWS::ApiGateway::Method' + Properties: + ApiKeyRequired: "false" + RestApiId: !Ref MyApi + ResourceId: !GetAtt + - MyApi + - RootResourceId + HttpMethod: GET + AuthorizationType: NONE + Integration: + Type: MOCK + MethodResponses: + - StatusCode : "200" + diff --git a/assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/test/positive_expected_result.json index 8e2869a5ddf..2862d01c542 100644 --- a/assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/api_gateway_method_does_not_contains_an_api_key/test/positive_expected_result.json @@ -1,9 +1,9 @@ [ { - "line": 7, - "fileName": "positive1.yaml", "queryName": "API Gateway Method Does Not Contains An API Key", - "severity": "MEDIUM" + "severity": "MEDIUM", + "line": 7, + "fileName": "positive1.yaml" }, { "queryName": "API Gateway Method Does Not Contains An API Key", @@ -22,5 +22,17 @@ "severity": "MEDIUM", "line": 6, "fileName": "positive4.json" + }, + { + "queryName": "API Gateway Method Does Not Contains An API Key", + "severity": "MEDIUM", + "line": 13, + "fileName": "positive5.json" + }, + { + "queryName": "API Gateway Method Does Not Contains An API Key", + "severity": "MEDIUM", + "line": 7, + "fileName": "positive6.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/api_gateway_xray_disabled/query.rego b/assets/queries/cloudFormation/aws/api_gateway_xray_disabled/query.rego index 6c3376dd3cf..6823abd1eb4 100644 --- a/assets/queries/cloudFormation/aws/api_gateway_xray_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/api_gateway_xray_disabled/query.rego @@ -8,7 +8,7 @@ CxPolicy[result] { resource = document[i].Resources[name] resource.Type == "AWS::ApiGateway::Stage" properties := resource.Properties - isResFalse(properties.TracingEnabled) + cf_lib.isCloudFormationFalse(properties.TracingEnabled) result := { "documentId": input.document[i].id, @@ -38,9 +38,3 @@ CxPolicy[result] { "keyActualValue": sprintf("Resources.%s.Properties.TracingEnabled is undefined", [name]), } } - -isResFalse(answer) { - answer == "false" -} else { - answer == false -} diff --git a/assets/queries/cloudFormation/aws/api_gateway_xray_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/api_gateway_xray_disabled/test/positive_expected_result.json index 254e8a93f37..8eeda87f4fb 100644 --- a/assets/queries/cloudFormation/aws/api_gateway_xray_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/api_gateway_xray_disabled/test/positive_expected_result.json @@ -1,15 +1,15 @@ [ { - "line": 13, - "fileName": "positive1.yaml", "queryName": "API Gateway X-Ray Disabled", - "severity": "LOW" + "severity": "LOW", + "line": 13, + "fileName": "positive1.yaml" }, { - "line": 6, - "fileName": "positive2.yaml", "queryName": "API Gateway X-Ray Disabled", - "severity": "LOW" + "severity": "LOW", + "line": 6, + "fileName": "positive2.yaml" }, { "queryName": "API Gateway X-Ray Disabled", diff --git a/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/query.rego b/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/query.rego index eedc5d6e865..1fa5df7af5d 100644 --- a/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/query.rego @@ -26,7 +26,7 @@ CxPolicy[result] { [path, Resources] := walk(docs) resource := Resources[name] resource.Type == "AWS::RDS::DBInstance" - resource.Properties.AutoMinorVersionUpgrade == false + cf_lib.isCloudFormationFalse(resource.Properties.AutoMinorVersionUpgrade) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/negative1.yaml b/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/negative1.yaml index 9395411d661..969f875e71a 100644 --- a/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/negative1.yaml +++ b/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/negative1.yaml @@ -1,10 +1,6 @@ -#this code is a correct code for which the query should not find any result AWSTemplateFormatVersion: 2010-09-09 Description: >- - Description": "AWS CloudFormation Sample Template for creating an Amazon RDS DB instance: - Sample template showing how to create a DB instance with Enhanced Monitoring enabled. - **WARNING** This template creates an RDS DB instance. You will be billed for the AWS - resources used if you create a stack from this template. + Description": "AWS CloudFormation Sample" Parameters: DBInstanceID: Default: mydbinstance @@ -16,41 +12,6 @@ Parameters: ConstraintDescription: >- Must begin with a letter and must not end with a hyphen or contain two consecutive hyphens. - DBName: - Default: mydb - Description: My database - Type: String - MinLength: '1' - MaxLength: '64' - AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*' - ConstraintDescription: Must begin with a letter and contain only alphanumeric characters. - DBInstanceClass: - Default: db.m5.large - Description: DB instance class - Type: String - ConstraintDescription: Must select a valid DB instance type. - DBAllocatedStorage: - Default: '50' - Description: The size of the database (GiB) - Type: Number - MinValue: '5' - MaxValue: '1024' - ConstraintDescription: must be between 20 and 65536 GiB. - DBUsername: - NoEcho: 'true' - Description: Username for MySQL database access - Type: String - MinLength: '1' - MaxLength: '16' - AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*' - ConstraintDescription: must begin with a letter and contain only alphanumeric characters. - DBPassword: - NoEcho: 'true' - Description: Password MySQL database access - Type: String - MinLength: '8' - MaxLength: '41' - AllowedPattern: '[a-zA-Z0-9]*' ConstraintDescription: must contain only alphanumeric characters. Resources: MyDB: diff --git a/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/negative2.json b/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/negative2.json index e612fa5c4c8..592e037fe1c 100644 --- a/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/negative2.json +++ b/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/negative2.json @@ -7,50 +7,6 @@ "ConstraintDescription": "Must select a valid DB instance type.", "Default": "db.m5.large", "Description": "DB instance class" - }, - "DBAllocatedStorage": { - "Default": "50", - "Description": "The size of the database (GiB)", - "Type": "Number", - "MinValue": "5", - "MaxValue": "1024", - "ConstraintDescription": "must be between 20 and 65536 GiB." - }, - "DBUsername": { - "NoEcho": "true", - "Description": "Username for MySQL database access", - "Type": "String", - "MinLength": "1", - "MaxLength": "16", - "AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*", - "ConstraintDescription": "must begin with a letter and contain only alphanumeric characters." - }, - "DBPassword": { - "ConstraintDescription": "must contain only alphanumeric characters.", - "NoEcho": "true", - "Description": "Password MySQL database access", - "Type": "String", - "MinLength": "8", - "MaxLength": "41", - "AllowedPattern": "[a-zA-Z0-9]*" - }, - "DBInstanceID": { - "Default": "mydbinstance", - "Description": "My database instance", - "Type": "String", - "MinLength": "1", - "MaxLength": "63", - "AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*", - "ConstraintDescription": "Must begin with a letter and must not end with a hyphen or contain two consecutive hyphens." - }, - "DBName": { - "ConstraintDescription": "Must begin with a letter and contain only alphanumeric characters.", - "Default": "mydb", - "Description": "My database", - "Type": "String", - "MinLength": "1", - "MaxLength": "64", - "AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*" } }, "Resources": { diff --git a/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/negative3.yaml new file mode 100644 index 00000000000..b971f058d01 --- /dev/null +++ b/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/negative3.yaml @@ -0,0 +1,30 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: >- + Description": "AWS CloudFormation Sample" +Parameters: + DBInstanceID: + Default: mydbinstance + Description: My database instance + Type: String + MinLength: '1' + MaxLength: '63' + AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*' + ConstraintDescription: >- + Must begin with a letter and must not end with a hyphen or contain two + consecutive hyphens. + ConstraintDescription: must contain only alphanumeric characters. +Resources: + MyDB: + Type: 'AWS::RDS::DBInstance' + Properties: + DBInstanceIdentifier: !Ref DBInstanceID + DBName: !Ref DBName + DBInstanceClass: !Ref DBInstanceClass + AllocatedStorage: !Ref DBAllocatedStorage + Engine: MySQL + EngineVersion: 8.0.16 + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + MonitoringInterval: '60' + MonitoringRoleArn: 'arn:aws:iam::123456789012:role/rds-monitoring-role' + AutoMinorVersionUpgrade: "true" \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/negative4.json b/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/negative4.json new file mode 100644 index 00000000000..79e5766fdb9 --- /dev/null +++ b/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/negative4.json @@ -0,0 +1,30 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z", + "Description": "Description\": \"AWS CloudFormation Sample Template for creating an Amazon RDS DB instance: Sample template showing how to create a DB instance with Enhanced Monitoring enabled. **WARNING** This template creates an RDS DB instance. You will be billed for the AWS resources used if you create a stack from this template.", + "Parameters": { + "DBInstanceClass": { + "Type": "String", + "ConstraintDescription": "Must select a valid DB instance type.", + "Default": "db.m5.large", + "Description": "DB instance class" + } + }, + "Resources": { + "MyDB": { + "Properties": { + "EngineVersion": "8.0.16", + "MasterUsername": "DBUsername", + "MonitoringInterval": "60", + "MonitoringRoleArn": "arn:aws:iam::123456789012:role/rds-monitoring-role", + "AutoMinorVersionUpgrade": "true", + "DBInstanceIdentifier": "DBInstanceID", + "DBInstanceClass": "DBInstanceClass", + "Engine": "MySQL", + "MasterUserPassword": "DBPassword", + "DBName": "DBName", + "AllocatedStorage": "DBAllocatedStorage" + }, + "Type": "AWS::RDS::DBInstance" + } + } +} diff --git a/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/positive1.yaml b/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/positive1.yaml index a574517fe65..ba53ac8fc87 100644 --- a/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/positive1.yaml +++ b/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/positive1.yaml @@ -1,10 +1,6 @@ -#this is a problematic code where the query should report a result(s) AWSTemplateFormatVersion: 2010-09-09 Description: >- - Description": "AWS CloudFormation Sample Template for creating an Amazon RDS DB instance: - Sample template showing how to create a DB instance with Enhanced Monitoring enabled. - **WARNING** This template creates an RDS DB instance. You will be billed for the AWS - resources used if you create a stack from this template. + Description": "AWS CloudFormation Sample " Parameters: DBInstanceID: Default: mydbinstance @@ -16,42 +12,6 @@ Parameters: ConstraintDescription: >- Must begin with a letter and must not end with a hyphen or contain two consecutive hyphens. - DBName: - Default: mydb - Description: My database - Type: String - MinLength: '1' - MaxLength: '64' - AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*' - ConstraintDescription: Must begin with a letter and contain only alphanumeric characters. - DBInstanceClass: - Default: db.m5.large - Description: DB instance class - Type: String - ConstraintDescription: Must select a valid DB instance type. - DBAllocatedStorage: - Default: '50' - Description: The size of the database (GiB) - Type: Number - MinValue: '5' - MaxValue: '1024' - ConstraintDescription: must be between 20 and 65536 GiB. - DBUsername: - NoEcho: 'true' - Description: Username for MySQL database access - Type: String - MinLength: '1' - MaxLength: '16' - AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*' - ConstraintDescription: must begin with a letter and contain only alphanumeric characters. - DBPassword: - NoEcho: 'true' - Description: Password MySQL database access - Type: String - MinLength: '8' - MaxLength: '41' - AllowedPattern: '[a-zA-Z0-9]*' - ConstraintDescription: must contain only alphanumeric characters. Resources: MyDB: Type: 'AWS::RDS::DBInstance' diff --git a/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/positive2.json b/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/positive2.json index 470c892233e..ccb65d22211 100644 --- a/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/positive2.json +++ b/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/positive2.json @@ -2,38 +2,6 @@ "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z", "Description": "Description\": \"AWS CloudFormation Sample Template for creating an Amazon RDS DB instance: Sample template showing how to create a DB instance with Enhanced Monitoring enabled. **WARNING** This template creates an RDS DB instance. You will be billed for the AWS resources used if you create a stack from this template.", "Parameters": { - "DBInstanceID": { - "Default": "mydbinstance", - "Description": "My database instance", - "Type": "String", - "MinLength": "1", - "MaxLength": "63", - "AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*", - "ConstraintDescription": "Must begin with a letter and must not end with a hyphen or contain two consecutive hyphens." - }, - "DBName": { - "Default": "mydb", - "Description": "My database", - "Type": "String", - "MinLength": "1", - "MaxLength": "64", - "AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*", - "ConstraintDescription": "Must begin with a letter and contain only alphanumeric characters." - }, - "DBInstanceClass": { - "Default": "db.m5.large", - "Description": "DB instance class", - "Type": "String", - "ConstraintDescription": "Must select a valid DB instance type." - }, - "DBAllocatedStorage": { - "Description": "The size of the database (GiB)", - "Type": "Number", - "MinValue": "5", - "MaxValue": "1024", - "ConstraintDescription": "must be between 20 and 65536 GiB.", - "Default": "50" - }, "DBUsername": { "NoEcho": "true", "Description": "Username for MySQL database access", @@ -42,15 +10,6 @@ "MaxLength": "16", "AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*", "ConstraintDescription": "must begin with a letter and contain only alphanumeric characters." - }, - "DBPassword": { - "NoEcho": "true", - "Description": "Password MySQL database access", - "Type": "String", - "MinLength": "8", - "MaxLength": "41", - "AllowedPattern": "[a-zA-Z0-9]*", - "ConstraintDescription": "must contain only alphanumeric characters." } }, "Resources": { diff --git a/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/positive3.yaml b/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/positive3.yaml new file mode 100644 index 00000000000..85132b989c7 --- /dev/null +++ b/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/positive3.yaml @@ -0,0 +1,42 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: >- + Description": "AWS CloudFormation Sample " +Parameters: + DBInstanceID: + Default: mydbinstance + Description: My database instance + Type: String + MinLength: '1' + MaxLength: '63' + AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*' + ConstraintDescription: >- + Must begin with a letter and must not end with a hyphen or contain two + consecutive hyphens. +Resources: + MyDB: + Type: 'AWS::RDS::DBInstance' + Properties: + DBInstanceIdentifier: !Ref DBInstanceID + DBName: !Ref DBName + DBInstanceClass: !Ref DBInstanceClass + AllocatedStorage: !Ref DBAllocatedStorage + Engine: MySQL + EngineVersion: 8.0.16 + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + MonitoringInterval: '60' + MonitoringRoleArn: 'arn:aws:iam::123456789012:role/rds-monitoring-role' + MyDB2: + Type: 'AWS::RDS::DBInstance' + Properties: + DBInstanceIdentifier: !Ref DBInstanceID + DBName: !Ref DBName + DBInstanceClass: !Ref DBInstanceClass + AllocatedStorage: !Ref DBAllocatedStorage + Engine: MySQL + EngineVersion: 8.0.16 + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + MonitoringInterval: '60' + MonitoringRoleArn: 'arn:aws:iam::123456789012:role/rds-monitoring-role' + AutoMinorVersionUpgrade: "false" \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/positive4.json b/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/positive4.json new file mode 100644 index 00000000000..6f994bec195 --- /dev/null +++ b/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/positive4.json @@ -0,0 +1,48 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z", + "Description": "Description\": \"AWS CloudFormation Sample Template for creating an Amazon RDS DB instance: Sample template showing how to create a DB instance with Enhanced Monitoring enabled. **WARNING** This template creates an RDS DB instance. You will be billed for the AWS resources used if you create a stack from this template.", + "Parameters": { + "DBUsername": { + "NoEcho": "true", + "Description": "Username for MySQL database access", + "Type": "String", + "MinLength": "1", + "MaxLength": "16", + "AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*", + "ConstraintDescription": "must begin with a letter and contain only alphanumeric characters." + } + }, + "Resources": { + "MyDB": { + "Properties": { + "DBInstanceIdentifier": "DBInstanceID", + "DBInstanceClass": "DBInstanceClass", + "Engine": "MySQL", + "MasterUserPassword": "DBPassword", + "MonitoringInterval": "60", + "MonitoringRoleArn": "arn:aws:iam::123456789012:role/rds-monitoring-role", + "DBName": "DBName", + "AllocatedStorage": "DBAllocatedStorage", + "EngineVersion": "8.0.16", + "MasterUsername": "DBUsername" + }, + "Type": "AWS::RDS::DBInstance" + }, + "MyDB2": { + "Type": "AWS::RDS::DBInstance", + "Properties": { + "DBInstanceIdentifier": "DBInstanceID", + "DBInstanceClass": "DBInstanceClass", + "EngineVersion": "8.0.16", + "MasterUserPassword": "DBPassword", + "MonitoringRoleArn": "arn:aws:iam::123456789012:role/rds-monitoring-role", + "DBName": "DBName", + "AllocatedStorage": "DBAllocatedStorage", + "Engine": "MySQL", + "MasterUsername": "DBUsername", + "MonitoringInterval": "60", + "AutoMinorVersionUpgrade": "false" + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/positive_expected_result.json index 213647b0431..a7a2b2484ab 100644 --- a/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/automatic_minor_upgrades_disabled/test/positive_expected_result.json @@ -2,25 +2,49 @@ { "queryName": "Automatic Minor Upgrades Disabled", "severity": "LOW", - "line": 58, + "line": 18, "fileName": "positive1.yaml" }, { "queryName": "Automatic Minor Upgrades Disabled", "severity": "LOW", - "line": 82, + "line": 42, "fileName": "positive1.yaml" }, { "queryName": "Automatic Minor Upgrades Disabled", "severity": "LOW", - "line": 58, + "line": 17, "fileName": "positive2.json" }, { - "line": 85, - "fileName": "positive2.json", "queryName": "Automatic Minor Upgrades Disabled", - "severity": "LOW" + "severity": "LOW", + "line": 44, + "fileName": "positive2.json" + }, + { + "queryName": "Automatic Minor Upgrades Disabled", + "severity": "LOW", + "line": 18, + "fileName": "positive3.yaml" + }, + { + "queryName": "Automatic Minor Upgrades Disabled", + "severity": "LOW", + "line": 42, + "fileName": "positive3.yaml" + }, + { + "queryName": "Automatic Minor Upgrades Disabled", + "severity": "LOW", + "line": 17, + "fileName": "positive4.json" + }, + { + "queryName": "Automatic Minor Upgrades Disabled", + "severity": "LOW", + "line": 44, + "fileName": "positive4.json" } ] diff --git a/assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/query.rego b/assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/query.rego index 0a20669ce04..898ab33a9a4 100644 --- a/assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/query.rego +++ b/assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/query.rego @@ -7,7 +7,7 @@ CxPolicy[result] { resource = document[i].Resources[name] resource.Type == "AWS::Batch::JobDefinition" properties := resource.Properties - properties.ContainerProperties.Privileged == true + cf_lib.isCloudFormationTrue(properties.ContainerProperties.Privileged) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/test/negative5.json b/assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/test/negative5.json new file mode 100644 index 00000000000..5a810dc52f2 --- /dev/null +++ b/assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/test/negative5.json @@ -0,0 +1,39 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "BatchJobDefinition", + "Resources": { + "JobDefinition": { + "Properties": { + "Type": "container", + "JobDefinitionName": "nvidia-smi", + "ContainerProperties": { + "Command": [ + "nvidia-smi" + ], + "JobRoleArn": "String", + "Vcpus": 2, + "ReadonlyRootFilesystem": true, + "Image": "nvidia/cuda", + "MountPoints": [ + { + "ReadOnly": false, + "SourceVolume": "nvidia", + "ContainerPath": "/usr/local/nvidia" + } + ], + "Volumes": [ + { + "Host": { + "SourcePath": "/var/lib/nvidia-docker/volumes/nvidia_driver/latest" + }, + "Name": "nvidia" + } + ], + "Memory": 2000, + "Privileged": "false" + } + }, + "Type": "AWS::Batch::JobDefinition" + } + } +} diff --git a/assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/test/negative6.yaml b/assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/test/negative6.yaml new file mode 100644 index 00000000000..fe2e6329432 --- /dev/null +++ b/assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/test/negative6.yaml @@ -0,0 +1,26 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "BatchJobDefinition" +Resources: + JobDefinition: + Type: AWS::Batch::JobDefinition + Properties: + Type: container + JobDefinitionName: nvidia-smi + ContainerProperties: + MountPoints: + - ReadOnly: false + SourceVolume: nvidia + ContainerPath: /usr/local/nvidia + Volumes: + - Host: + SourcePath: /var/lib/nvidia-docker/volumes/nvidia_driver/latest + Name: nvidia + Command: + - nvidia-smi + Memory: 2000 + Privileged: "false" + JobRoleArn: String + ReadonlyRootFilesystem: true + Vcpus: 2 + Image: nvidia/cuda + diff --git a/assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/test/positive3.yaml b/assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/test/positive3.yaml new file mode 100644 index 00000000000..8a1aa669a25 --- /dev/null +++ b/assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/test/positive3.yaml @@ -0,0 +1,25 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "BatchJobDefinition" +Resources: + JobDefinition: + Type: AWS::Batch::JobDefinition + Properties: + Type: container + JobDefinitionName: nvidia-smi + ContainerProperties: + MountPoints: + - ReadOnly: false + SourceVolume: nvidia + ContainerPath: /usr/local/nvidia + Volumes: + - Host: + SourcePath: /var/lib/nvidia-docker/volumes/nvidia_driver/latest + Name: nvidia + Command: + - nvidia-smi + Memory: 2000 + Privileged: "true" + JobRoleArn: String + ReadonlyRootFilesystem: true + Vcpus: 2 + Image: nvidia/cuda diff --git a/assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/test/positive4.json b/assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/test/positive4.json new file mode 100644 index 00000000000..b0bda736b7f --- /dev/null +++ b/assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/test/positive4.json @@ -0,0 +1,39 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "BatchJobDefinition", + "Resources": { + "JobDefinition": { + "Type": "AWS::Batch::JobDefinition", + "Properties": { + "Type": "container", + "JobDefinitionName": "nvidia-smi", + "ContainerProperties": { + "Memory": 2000, + "Privileged": "true", + "Vcpus": 2, + "MountPoints": [ + { + "ReadOnly": false, + "SourceVolume": "nvidia", + "ContainerPath": "/usr/local/nvidia" + } + ], + "Command": [ + "nvidia-smi" + ], + "ReadonlyRootFilesystem": true, + "Image": "nvidia/cuda", + "Volumes": [ + { + "Host": { + "SourcePath": "/var/lib/nvidia-docker/volumes/nvidia_driver/latest" + }, + "Name": "nvidia" + } + ], + "JobRoleArn": "String" + } + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/test/positive_expected_result.json index a922abba472..2a6d712aed3 100644 --- a/assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/batch_job_definition_with_privileged_container_properties/test/positive_expected_result.json @@ -1,14 +1,26 @@ [ { - "line": 21, - "fileName": "positive1.yaml", "queryName": "Batch Job Definition With Privileged Container Properties", - "severity": "HIGH" + "severity": "HIGH", + "line": 21, + "fileName": "positive1.yaml" }, { "queryName": "Batch Job Definition With Privileged Container Properties", "severity": "HIGH", "line": 12, "fileName": "positive2.json" + }, + { + "queryName": "Batch Job Definition With Privileged Container Properties", + "severity": "HIGH", + "line": 21, + "fileName": "positive3.yaml" + }, + { + "queryName": "Batch Job Definition With Privileged Container Properties", + "severity": "HIGH", + "line": 12, + "fileName": "positive4.json" } ] diff --git a/assets/queries/cloudFormation/aws/cdn_configuration_is_missing/query.rego b/assets/queries/cloudFormation/aws/cdn_configuration_is_missing/query.rego index daf2f58caa7..c3576e76e8e 100644 --- a/assets/queries/cloudFormation/aws/cdn_configuration_is_missing/query.rego +++ b/assets/queries/cloudFormation/aws/cdn_configuration_is_missing/query.rego @@ -10,7 +10,7 @@ CxPolicy[result] { resource.Type == "AWS::CloudFront::Distribution" distributionConfig := resource.Properties.DistributionConfig - isFalse(distributionConfig.Enabled) + cf_lib.isCloudFormationFalse(distributionConfig.Enabled) result := { "documentId": input.document[i].id, @@ -43,8 +43,3 @@ CxPolicy[result] { } } -isFalse(value) { - value == false -} else { - value == "false" -} diff --git a/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/query.rego b/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/query.rego index bce0a237387..e50eaf7f86f 100644 --- a/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/query.rego @@ -22,7 +22,7 @@ CxPolicy[result] { CxPolicy[result] { resource := input.document[i].Resources[name] resource.Type == "AWS::CloudTrail::Trail" - resource.Properties.EnableLogFileValidation == false + cf_lib.isCloudFormationFalse(resource.Properties.EnableLogFileValidation) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/negative2.json b/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/negative2.json index d1e540818de..03e65544a9c 100644 --- a/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/negative2.json +++ b/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/negative2.json @@ -89,7 +89,7 @@ "Properties": { "IsLogging": true, "IsMultiRegionTrail": true, - "EnableLogFileValidation": true, + "EnableLogFileValidation": "true", "S3BucketName": { "Ref": "S3Bucket" }, diff --git a/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/negative3.yaml new file mode 100644 index 00000000000..c592f856bab --- /dev/null +++ b/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/negative3.yaml @@ -0,0 +1,71 @@ +AWSTemplateFormatVersion: "2010-09-09" +Parameters: + OperatorEmail: + Description: "Email address to notify when new logs are published." + Type: String +Resources: + S3Bucket: + DeletionPolicy: Retain + Type: AWS::S3::Bucket + Properties: {} + BucketPolicy: + Type: AWS::S3::BucketPolicy + Properties: + Bucket: + Ref: S3Bucket + PolicyDocument: + Version: "2012-10-17" + Statement: + - Sid: "AWSCloudTrailAclCheck" + Effect: "Allow" + Principal: + Service: "cloudtrail.amazonaws.com" + Action: "s3:GetBucketAcl" + Resource: !Sub |- + arn:aws:s3:::${S3Bucket} + - Sid: "AWSCloudTrailWrite" + Effect: "Allow" + Principal: + Service: "cloudtrail.amazonaws.com" + Action: "s3:PutObject" + Resource: !Sub |- + arn:aws:s3:::${S3Bucket}/AWSLogs/${AWS::AccountId}/* + Condition: + StringEquals: + s3:x-amz-acl: "bucket-owner-full-control" + Topic: + Type: AWS::SNS::Topic + Properties: + Subscription: + - Endpoint: + Ref: OperatorEmail + Protocol: email + TopicPolicy: + Type: AWS::SNS::TopicPolicy + Properties: + Topics: + - Ref: "Topic" + PolicyDocument: + Version: "2008-10-17" + Statement: + - Sid: "AWSCloudTrailSNSPolicy" + Effect: "Allow" + Principal: + Service: "cloudtrail.amazonaws.com" + Resource: "*" + Action: "SNS:Publish" + myTrail: + DependsOn: + - BucketPolicy + - TopicPolicy + Type: AWS::CloudTrail::Trail + Properties: + EnableLogFileValidation: "true" + S3BucketName: + Ref: S3Bucket + SnsTopicName: + Fn::GetAtt: + - Topic + - TopicName + IsLogging: true + IsMultiRegionTrail: true diff --git a/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/negative4.json b/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/negative4.json new file mode 100644 index 00000000000..d1e540818de --- /dev/null +++ b/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/negative4.json @@ -0,0 +1,110 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Parameters": { + "OperatorEmail": { + "Type": "String", + "Description": "Email address to notify when new logs are published." + } + }, + "Resources": { + "BucketPolicy": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "S3Bucket" + }, + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Principal": { + "Service": "cloudtrail.amazonaws.com" + }, + "Action": "s3:GetBucketAcl", + "Resource": "arn:aws:s3:::${S3Bucket}", + "Sid": "AWSCloudTrailAclCheck", + "Effect": "Allow" + }, + { + "Effect": "Allow", + "Principal": { + "Service": "cloudtrail.amazonaws.com" + }, + "Action": "s3:PutObject", + "Resource": "arn:aws:s3:::${S3Bucket}/AWSLogs/${AWS::AccountId}/*", + "Condition": { + "StringEquals": { + "s3:x-amz-acl": "bucket-owner-full-control" + } + }, + "Sid": "AWSCloudTrailWrite" + } + ] + } + } + }, + "Topic": { + "Type": "AWS::SNS::Topic", + "Properties": { + "Subscription": [ + { + "Endpoint": { + "Ref": "OperatorEmail" + }, + "Protocol": "email" + } + ] + } + }, + "TopicPolicy": { + "Type": "AWS::SNS::TopicPolicy", + "Properties": { + "Topics": [ + { + "Ref": "Topic" + } + ], + "PolicyDocument": { + "Version": "2008-10-17", + "Statement": [ + { + "Sid": "AWSCloudTrailSNSPolicy", + "Effect": "Allow", + "Principal": { + "Service": "cloudtrail.amazonaws.com" + }, + "Resource": "*", + "Action": "SNS:Publish" + } + ] + } + } + }, + "myTrail": { + "DependsOn": [ + "BucketPolicy", + "TopicPolicy" + ], + "Type": "AWS::CloudTrail::Trail", + "Properties": { + "IsLogging": true, + "IsMultiRegionTrail": true, + "EnableLogFileValidation": true, + "S3BucketName": { + "Ref": "S3Bucket" + }, + "SnsTopicName": { + "Fn::GetAtt": [ + "Topic", + "TopicName" + ] + } + } + }, + "S3Bucket": { + "DeletionPolicy": "Retain", + "Type": "AWS::S3::Bucket", + "Properties": {} + } + } +} diff --git a/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/positive3.yaml b/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/positive3.yaml new file mode 100644 index 00000000000..710dd6b96d1 --- /dev/null +++ b/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/positive3.yaml @@ -0,0 +1,85 @@ +AWSTemplateFormatVersion: "2010-09-09" +Parameters: + OperatorEmail: + Description: "Email address to notify when new logs are published." + Type: String +Resources: + S3Bucket: + DeletionPolicy: Retain + Type: AWS::S3::Bucket + Properties: {} + BucketPolicy: + Type: AWS::S3::BucketPolicy + Properties: + Bucket: + Ref: S3Bucket + PolicyDocument: + Version: "2012-10-17" + Statement: + - Sid: "AWSCloudTrailAclCheck" + Effect: "Allow" + Principal: + Service: "cloudtrail.amazonaws.com" + Action: "s3:GetBucketAcl" + Resource: !Sub |- + arn:aws:s3:::${S3Bucket} + - Sid: "AWSCloudTrailWrite" + Effect: "Allow" + Principal: + Service: "cloudtrail.amazonaws.com" + Action: "s3:PutObject" + Resource: !Sub |- + arn:aws:s3:::${S3Bucket}/AWSLogs/${AWS::AccountId}/* + Condition: + StringEquals: + s3:x-amz-acl: "bucket-owner-full-control" + Topic: + Type: AWS::SNS::Topic + Properties: + Subscription: + - Endpoint: + Ref: OperatorEmail + Protocol: email + TopicPolicy: + Type: AWS::SNS::TopicPolicy + Properties: + Topics: + - Ref: "Topic" + PolicyDocument: + Version: "2008-10-17" + Statement: + - Sid: "AWSCloudTrailSNSPolicy" + Effect: "Allow" + Principal: + Service: "cloudtrail.amazonaws.com" + Resource: "*" + Action: "SNS:Publish" + myTrail: + DependsOn: + - BucketPolicy + - TopicPolicy + Type: AWS::CloudTrail::Trail + Properties: + S3BucketName: + Ref: S3Bucket + SnsTopicName: + Fn::GetAtt: + - Topic + - TopicName + IsLogging: true + IsMultiRegionTrail: true + myTrail2: + DependsOn: + - BucketPolicy + - TopicPolicy + Type: AWS::CloudTrail::Trail + Properties: + EnableLogFileValidation: false + S3BucketName: + Ref: S3Bucket + SnsTopicName: + Fn::GetAtt: + - Topic + - TopicName + IsLogging: true + IsMultiRegionTrail: "true" diff --git a/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/positive4.json b/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/positive4.json new file mode 100644 index 00000000000..9deaa288ac0 --- /dev/null +++ b/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/positive4.json @@ -0,0 +1,130 @@ +{ + "Resources": { + "S3Bucket": { + "DeletionPolicy": "Retain", + "Type": "AWS::S3::Bucket", + "Properties": {} + }, + "BucketPolicy": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "S3Bucket" + }, + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "AWSCloudTrailAclCheck", + "Effect": "Allow", + "Principal": { + "Service": "cloudtrail.amazonaws.com" + }, + "Action": "s3:GetBucketAcl", + "Resource": "arn:aws:s3:::${S3Bucket}" + }, + { + "Resource": "arn:aws:s3:::${S3Bucket}/AWSLogs/${AWS::AccountId}/*", + "Condition": { + "StringEquals": { + "s3:x-amz-acl": "bucket-owner-full-control" + } + }, + "Sid": "AWSCloudTrailWrite", + "Effect": "Allow", + "Principal": { + "Service": "cloudtrail.amazonaws.com" + }, + "Action": "s3:PutObject" + } + ] + } + } + }, + "Topic": { + "Type": "AWS::SNS::Topic", + "Properties": { + "Subscription": [ + { + "Endpoint": { + "Ref": "OperatorEmail" + }, + "Protocol": "email" + } + ] + } + }, + "TopicPolicy": { + "Properties": { + "Topics": [ + { + "Ref": "Topic" + } + ], + "PolicyDocument": { + "Version": "2008-10-17", + "Statement": [ + { + "Sid": "AWSCloudTrailSNSPolicy", + "Effect": "Allow", + "Principal": { + "Service": "cloudtrail.amazonaws.com" + }, + "Resource": "*", + "Action": "SNS:Publish" + } + ] + } + }, + "Type": "AWS::SNS::TopicPolicy" + }, + "myTrail": { + "DependsOn": [ + "BucketPolicy", + "TopicPolicy" + ], + "Type": "AWS::CloudTrail::Trail", + "Properties": { + "IsMultiRegionTrail": "true", + "S3BucketName": { + "Ref": "S3Bucket" + }, + "SnsTopicName": { + "Fn::GetAtt": [ + "Topic", + "TopicName" + ] + }, + "IsLogging": true + } + }, + "myTrail2": { + "DependsOn": [ + "BucketPolicy", + "TopicPolicy" + ], + "Type": "AWS::CloudTrail::Trail", + "Properties": { + "EnableLogFileValidation": false, + "S3BucketName": { + "Ref": "S3Bucket" + }, + "SnsTopicName": { + "Fn::GetAtt": [ + "Topic", + "TopicName" + ] + }, + "IsLogging": true, + "IsMultiRegionTrail": "true" + } + } + }, + "AWSTemplateFormatVersion": "2010-09-09", + "Parameters": { + "OperatorEmail": { + "Description": "Email address to notify when new logs are published.", + "Type": "String" + } + } +} diff --git a/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/positive_expected_result.json index 637073ea5a0..0a532feff98 100644 --- a/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/cloudtrail_log_file_validation_disabled/test/positive_expected_result.json @@ -12,15 +12,39 @@ "fileName": "positive1.yaml" }, { - "line": 87, - "fileName": "positive2.json", "queryName": "CloudTrail Log File Validation Disabled", - "severity": "LOW" + "severity": "LOW", + "line": 87, + "fileName": "positive2.json" }, { "queryName": "CloudTrail Log File Validation Disabled", "severity": "LOW", "line": 108, "fileName": "positive2.json" + }, + { + "queryName": "CloudTrail Log File Validation Disabled", + "severity": "LOW", + "line": 62, + "fileName": "positive3.yaml" + }, + { + "queryName": "CloudTrail Log File Validation Disabled", + "severity": "LOW", + "line": 77, + "fileName": "positive3.yaml" + }, + { + "queryName": "CloudTrail Log File Validation Disabled", + "severity": "LOW", + "line": 87, + "fileName": "positive4.json" + }, + { + "queryName": "CloudTrail Log File Validation Disabled", + "severity": "LOW", + "line": 108, + "fileName": "positive4.json" } ] diff --git a/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/query.rego b/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/query.rego index b07ec97aef9..9bc8085feee 100644 --- a/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/query.rego @@ -5,7 +5,7 @@ import data.generic.cloudformation as cf_lib CxPolicy[result] { resource := input.document[i].Resources[name] resource.Type == "AWS::CloudTrail::Trail" - resource.Properties.IsLogging == false + cf_lib.isCloudFormationFalse(resource.Properties.IsLogging) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/negative1.yaml b/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/negative1.yaml index 0baee6cc25a..739b177bbfb 100644 --- a/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/negative1.yaml +++ b/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/negative1.yaml @@ -4,56 +4,6 @@ Parameters: Description: "Email address to notify when new logs are published." Type: String Resources: - S3Bucket: - DeletionPolicy: Retain - Type: AWS::S3::Bucket - Properties: {} - BucketPolicy: - Type: AWS::S3::BucketPolicy - Properties: - Bucket: - Ref: S3Bucket - PolicyDocument: - Version: "2012-10-17" - Statement: - - Sid: "AWSCloudTrailAclCheck" - Effect: "Allow" - Principal: - Service: "cloudtrail.amazonaws.com" - Action: "s3:GetBucketAcl" - Resource: !Sub |- - arn:aws:s3:::${S3Bucket} - - Sid: "AWSCloudTrailWrite" - Effect: "Allow" - Principal: - Service: "cloudtrail.amazonaws.com" - Action: "s3:PutObject" - Resource: !Sub |- - arn:aws:s3:::${S3Bucket}/AWSLogs/${AWS::AccountId}/* - Condition: - StringEquals: - s3:x-amz-acl: "bucket-owner-full-control" - Topic: - Type: AWS::SNS::Topic - Properties: - Subscription: - - Endpoint: - Ref: OperatorEmail - Protocol: email - TopicPolicy: - Type: AWS::SNS::TopicPolicy - Properties: - Topics: - - Ref: "Topic" - PolicyDocument: - Version: "2008-10-17" - Statement: - - Sid: "AWSCloudTrailSNSPolicy" - Effect: "Allow" - Principal: - Service: "cloudtrail.amazonaws.com" - Resource: "*" - Action: "SNS:Publish" myTrail: DependsOn: - BucketPolicy diff --git a/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/negative2.json b/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/negative2.json index 21f7b497228..53b22c898d8 100644 --- a/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/negative2.json +++ b/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/negative2.json @@ -7,79 +7,6 @@ } }, "Resources": { - "BucketPolicy": { - "Type": "AWS::S3::BucketPolicy", - "Properties": { - "Bucket": { - "Ref": "S3Bucket" - }, - "PolicyDocument": { - "Version": "2012-10-17", - "Statement": [ - { - "Principal": { - "Service": "cloudtrail.amazonaws.com" - }, - "Action": "s3:GetBucketAcl", - "Resource": "arn:aws:s3:::${S3Bucket}", - "Sid": "AWSCloudTrailAclCheck", - "Effect": "Allow" - }, - { - "Effect": "Allow", - "Principal": { - "Service": "cloudtrail.amazonaws.com" - }, - "Action": "s3:PutObject", - "Resource": "arn:aws:s3:::${S3Bucket}/AWSLogs/${AWS::AccountId}/*", - "Condition": { - "StringEquals": { - "s3:x-amz-acl": "bucket-owner-full-control" - } - }, - "Sid": "AWSCloudTrailWrite" - } - ] - } - } - }, - "Topic": { - "Type": "AWS::SNS::Topic", - "Properties": { - "Subscription": [ - { - "Endpoint": { - "Ref": "OperatorEmail" - }, - "Protocol": "email" - } - ] - } - }, - "TopicPolicy": { - "Type": "AWS::SNS::TopicPolicy", - "Properties": { - "Topics": [ - { - "Ref": "Topic" - } - ], - "PolicyDocument": { - "Version": "2008-10-17", - "Statement": [ - { - "Sid": "AWSCloudTrailSNSPolicy", - "Effect": "Allow", - "Principal": { - "Service": "cloudtrail.amazonaws.com" - }, - "Resource": "*", - "Action": "SNS:Publish" - } - ] - } - } - }, "myTrail2": { "DependsOn": [ "BucketPolicy", diff --git a/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/negative3.yaml new file mode 100644 index 00000000000..f882bfecb58 --- /dev/null +++ b/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/negative3.yaml @@ -0,0 +1,21 @@ +AWSTemplateFormatVersion: "2010-09-09" +Parameters: + OperatorEmail: + Description: "Email address to notify when new logs are published." + Type: String +Resources: + myTrail: + DependsOn: + - BucketPolicy + - TopicPolicy + Type: AWS::CloudTrail::Trail + Properties: + EnableLogFileValidation: "true" + S3BucketName: + Ref: S3Bucket + SnsTopicName: + Fn::GetAtt: + - Topic + - TopicName + IsLogging: "true" + IsMultiRegionTrail: "true" diff --git a/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/negative4.json b/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/negative4.json new file mode 100644 index 00000000000..7c5b23a0db4 --- /dev/null +++ b/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/negative4.json @@ -0,0 +1,37 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Parameters": { + "OperatorEmail": { + "Type": "String", + "Description": "Email address to notify when new logs are published." + } + }, + "Resources": { + "myTrail2": { + "DependsOn": [ + "BucketPolicy", + "TopicPolicy" + ], + "Type": "AWS::CloudTrail::Trail", + "Properties": { + "IsLogging": "true", + "IsMultiRegionTrail": "true", + "EnableLogFileValidation": "true", + "S3BucketName": { + "Ref": "S3Bucket" + }, + "SnsTopicName": { + "Fn::GetAtt": [ + "Topic", + "TopicName" + ] + } + } + }, + "S3Bucket": { + "DeletionPolicy": "Retain", + "Type": "AWS::S3::Bucket", + "Properties": {} + } + } +} diff --git a/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/positive1.yaml b/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/positive1.yaml index e6c2f4abced..71729b89d53 100644 --- a/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/positive1.yaml +++ b/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/positive1.yaml @@ -4,56 +4,6 @@ Parameters: Description: "Email address to notify when new logs are published." Type: String Resources: - S3Bucket: - DeletionPolicy: Retain - Type: AWS::S3::Bucket - Properties: {} - BucketPolicy: - Type: AWS::S3::BucketPolicy - Properties: - Bucket: - Ref: S3Bucket - PolicyDocument: - Version: "2012-10-17" - Statement: - - Sid: "AWSCloudTrailAclCheck" - Effect: "Allow" - Principal: - Service: "cloudtrail.amazonaws.com" - Action: "s3:GetBucketAcl" - Resource: !Sub |- - arn:aws:s3:::${S3Bucket} - - Sid: "AWSCloudTrailWrite" - Effect: "Allow" - Principal: - Service: "cloudtrail.amazonaws.com" - Action: "s3:PutObject" - Resource: !Sub |- - arn:aws:s3:::${S3Bucket}/AWSLogs/${AWS::AccountId}/* - Condition: - StringEquals: - s3:x-amz-acl: "bucket-owner-full-control" - Topic: - Type: AWS::SNS::Topic - Properties: - Subscription: - - Endpoint: - Ref: OperatorEmail - Protocol: email - TopicPolicy: - Type: AWS::SNS::TopicPolicy - Properties: - Topics: - - Ref: "Topic" - PolicyDocument: - Version: "2008-10-17" - Statement: - - Sid: "AWSCloudTrailSNSPolicy" - Effect: "Allow" - Principal: - Service: "cloudtrail.amazonaws.com" - Resource: "*" - Action: "SNS:Publish" myTrail3: DependsOn: - BucketPolicy diff --git a/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/positive2.json b/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/positive2.json index 5d13c272bea..8662bbf3004 100644 --- a/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/positive2.json +++ b/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/positive2.json @@ -5,79 +5,6 @@ "Type": "AWS::S3::Bucket", "Properties": {} }, - "BucketPolicy": { - "Type": "AWS::S3::BucketPolicy", - "Properties": { - "Bucket": { - "Ref": "S3Bucket" - }, - "PolicyDocument": { - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "AWSCloudTrailAclCheck", - "Effect": "Allow", - "Principal": { - "Service": "cloudtrail.amazonaws.com" - }, - "Action": "s3:GetBucketAcl", - "Resource": "arn:aws:s3:::${S3Bucket}" - }, - { - "Resource": "arn:aws:s3:::${S3Bucket}/AWSLogs/${AWS::AccountId}/*", - "Condition": { - "StringEquals": { - "s3:x-amz-acl": "bucket-owner-full-control" - } - }, - "Sid": "AWSCloudTrailWrite", - "Effect": "Allow", - "Principal": { - "Service": "cloudtrail.amazonaws.com" - }, - "Action": "s3:PutObject" - } - ] - } - } - }, - "Topic": { - "Type": "AWS::SNS::Topic", - "Properties": { - "Subscription": [ - { - "Endpoint": { - "Ref": "OperatorEmail" - }, - "Protocol": "email" - } - ] - } - }, - "TopicPolicy": { - "Properties": { - "Topics": [ - { - "Ref": "Topic" - } - ], - "PolicyDocument": { - "Version": "2008-10-17", - "Statement": [ - { - "Sid": "AWSCloudTrailSNSPolicy", - "Effect": "Allow", - "Principal": { - "Service": "cloudtrail.amazonaws.com" - }, - "Resource": "*", - "Action": "SNS:Publish" - } - ] - } - }, - "Type": "AWS::SNS::TopicPolicy" - }, "myTrail5": { "DependsOn": [ "BucketPolicy", diff --git a/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/positive3.yaml b/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/positive3.yaml new file mode 100644 index 00000000000..b8e16ef53de --- /dev/null +++ b/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/positive3.yaml @@ -0,0 +1,21 @@ +AWSTemplateFormatVersion: "2010-09-09" +Parameters: + OperatorEmail: + Description: "Email address to notify when new logs are published." + Type: String +Resources: + myTrail: + DependsOn: + - BucketPolicy + - TopicPolicy + Type: AWS::CloudTrail::Trail + Properties: + EnableLogFileValidation: false + S3BucketName: + Ref: S3Bucket + SnsTopicName: + Fn::GetAtt: + - Topic + - TopicName + IsLogging: false + IsMultiRegionTrail: "true" diff --git a/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/positive4.json b/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/positive4.json new file mode 100644 index 00000000000..b1c2795ee4d --- /dev/null +++ b/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/positive4.json @@ -0,0 +1,36 @@ +{ + "Resources": { + "S3Bucket": { + "DeletionPolicy": "Retain", + "Type": "AWS::S3::Bucket", + "Properties": {} + }, + "myTrail5": { + "DependsOn": [ + "BucketPolicy", + "TopicPolicy" + ], + "Type": "AWS::CloudTrail::Trail", + "Properties": { + "IsMultiRegionTrail": "true", + "S3BucketName": { + "Ref": "S3Bucket" + }, + "SnsTopicName": { + "Fn::GetAtt": [ + "Topic", + "TopicName" + ] + }, + "IsLogging": false + } + } + }, + "AWSTemplateFormatVersion": "2010-09-09", + "Parameters": { + "OperatorEmail": { + "Description": "Email address to notify when new logs are published.", + "Type": "String" + } + } +} diff --git a/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/positive_expected_result.json index 8963c2ee9b2..989c8dbedb1 100644 --- a/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/cloudtrail_logging_disabled/test/positive_expected_result.json @@ -2,25 +2,37 @@ { "queryName": "CloudTrail Logging Disabled", "severity": "MEDIUM", - "line": 69, + "line": 19, "fileName": "positive1.yaml" }, { "queryName": "CloudTrail Logging Disabled", "severity": "MEDIUM", - "line": 84, + "line": 34, "fileName": "positive1.yaml" }, { - "line": 98, - "fileName": "positive2.json", "queryName": "CloudTrail Logging Disabled", - "severity": "MEDIUM" + "severity": "MEDIUM", + "line": 25, + "fileName": "positive2.json" }, { "queryName": "CloudTrail Logging Disabled", "severity": "MEDIUM", - "line": 118, + "line": 45, "fileName": "positive2.json" + }, + { + "queryName": "CloudTrail Logging Disabled", + "severity": "MEDIUM", + "line": 20, + "fileName": "positive3.yaml" + }, + { + "queryName": "CloudTrail Logging Disabled", + "severity": "MEDIUM", + "line": 25, + "fileName": "positive4.json" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/cloudtrail_multi_region_disabled/query.rego b/assets/queries/cloudFormation/aws/cloudtrail_multi_region_disabled/query.rego index b15268289ab..0f2e2454e43 100644 --- a/assets/queries/cloudFormation/aws/cloudtrail_multi_region_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/cloudtrail_multi_region_disabled/query.rego @@ -7,7 +7,8 @@ CxPolicy[result] { resource := input.document[i].Resources[name] resource.Type == "AWS::CloudTrail::Trail" common_lib.valid_key(resource.Properties, "IsMultiRegionTrail") - not checkRegion(resource) + + not cf_lib.isCloudFormationTrue(resource.Properties.IsMultiRegionTrail) result := { "documentId": input.document[i].id, @@ -16,7 +17,7 @@ CxPolicy[result] { "searchKey": sprintf("Resources.%s.Properties.IsMultiRegionTrail", [name]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("'Resources.%s.Properties.IsMultiRegionTrail' should be true", [name]), - "keyActualValue": sprintf("'Resources.%s.Properties.IsMultiRegionTrail' is false", [name]), + "keyActualValue": sprintf("'Resources.%s.Properties.IsMultiRegionTrail' is not true", [name]), } } @@ -36,6 +37,3 @@ CxPolicy[result] { } } -checkRegion(cltr) { - cltr.Properties.IsMultiRegionTrail == true -} diff --git a/assets/queries/cloudFormation/aws/cloudtrail_multi_region_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/cloudtrail_multi_region_disabled/test/negative3.yaml new file mode 100644 index 00000000000..cb27107548f --- /dev/null +++ b/assets/queries/cloudFormation/aws/cloudtrail_multi_region_disabled/test/negative3.yaml @@ -0,0 +1,70 @@ +AWSTemplateFormatVersion: "2010-09-09" +Parameters: + OperatorEmail: + Description: "Email address to notify when new logs are published." + Type: String +Resources: + S3Bucket: + DeletionPolicy: Retain + Type: AWS::S3::Bucket + Properties: {} + BucketPolicy: + Type: AWS::S3::BucketPolicy + Properties: + Bucket: + Ref: S3Bucket + PolicyDocument: + Version: "2012-10-17" + Statement: + - Sid: "AWSCloudTrailAclCheck" + Effect: "Allow" + Principal: + Service: "cloudtrail.amazonaws.com" + Action: "s3:GetBucketAcl" + Resource: !Sub |- + arn:aws:s3:::${S3Bucket} + - Sid: "AWSCloudTrailWrite" + Effect: "Allow" + Principal: + Service: "cloudtrail.amazonaws.com" + Action: "s3:PutObject" + Resource: !Sub |- + arn:aws:s3:::${S3Bucket}/AWSLogs/${AWS::AccountId}/* + Condition: + StringEquals: + s3:x-amz-acl: "bucket-owner-full-control" + Topic: + Type: AWS::SNS::Topic + Properties: + Subscription: + - Endpoint: + Ref: OperatorEmail + Protocol: email + TopicPolicy: + Type: AWS::SNS::TopicPolicy + Properties: + Topics: + - Ref: "Topic" + PolicyDocument: + Version: "2008-10-17" + Statement: + - Sid: "AWSCloudTrailSNSPolicy" + Effect: "Allow" + Principal: + Service: "cloudtrail.amazonaws.com" + Resource: "*" + Action: "SNS:Publish" + myTrail: + DependsOn: + - BucketPolicy + - TopicPolicy + Type: AWS::CloudTrail::Trail + Properties: + S3BucketName: + Ref: S3Bucket + SnsTopicName: + Fn::GetAtt: + - Topic + - TopicName + IsLogging: true + IsMultiRegionTrail: "true" diff --git a/assets/queries/cloudFormation/aws/cloudtrail_multi_region_disabled/test/negative4.json b/assets/queries/cloudFormation/aws/cloudtrail_multi_region_disabled/test/negative4.json new file mode 100644 index 00000000000..1cb88fd10e9 --- /dev/null +++ b/assets/queries/cloudFormation/aws/cloudtrail_multi_region_disabled/test/negative4.json @@ -0,0 +1,109 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Parameters": { + "OperatorEmail": { + "Description": "Email address to notify when new logs are published.", + "Type": "String" + } + }, + "Resources": { + "TopicPolicy": { + "Type": "AWS::SNS::TopicPolicy", + "Properties": { + "Topics": [ + { + "Ref": "Topic" + } + ], + "PolicyDocument": { + "Version": "2008-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "cloudtrail.amazonaws.com" + }, + "Resource": "*", + "Action": "SNS:Publish", + "Sid": "AWSCloudTrailSNSPolicy" + } + ] + } + } + }, + "myTrail": { + "Type": "AWS::CloudTrail::Trail", + "Properties": { + "S3BucketName": { + "Ref": "S3Bucket" + }, + "SnsTopicName": { + "Fn::GetAtt": [ + "Topic", + "TopicName" + ] + }, + "IsLogging": true, + "IsMultiRegionTrail": "true" + }, + "DependsOn": [ + "BucketPolicy", + "TopicPolicy" + ] + }, + "S3Bucket": { + "Properties": {}, + "DeletionPolicy": "Retain", + "Type": "AWS::S3::Bucket" + }, + "BucketPolicy": { + "Properties": { + "Bucket": { + "Ref": "S3Bucket" + }, + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Principal": { + "Service": "cloudtrail.amazonaws.com" + }, + "Action": "s3:GetBucketAcl", + "Resource": "arn:aws:s3:::${S3Bucket}", + "Sid": "AWSCloudTrailAclCheck", + "Effect": "Allow" + }, + { + "Effect": "Allow", + "Principal": { + "Service": "cloudtrail.amazonaws.com" + }, + "Action": "s3:PutObject", + "Resource": "arn:aws:s3:::${S3Bucket}/AWSLogs/${AWS::AccountId}/*", + "Condition": { + "StringEquals": { + "s3:x-amz-acl": "bucket-owner-full-control" + } + }, + "Sid": "AWSCloudTrailWrite" + } + ] + } + }, + "Type": "AWS::S3::BucketPolicy" + }, + "Topic": { + "Type": "AWS::SNS::Topic", + "Properties": { + "Subscription": [ + { + "Endpoint": { + "Ref": "OperatorEmail" + }, + "Protocol": "email" + } + ] + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/cloudtrail_multi_region_disabled/test/positive3.yaml b/assets/queries/cloudFormation/aws/cloudtrail_multi_region_disabled/test/positive3.yaml new file mode 100644 index 00000000000..1de716f14f5 --- /dev/null +++ b/assets/queries/cloudFormation/aws/cloudtrail_multi_region_disabled/test/positive3.yaml @@ -0,0 +1,70 @@ +AWSTemplateFormatVersion: "2010-09-09" +Parameters: + OperatorEmail: + Description: "Email address to notify when new logs are published." + Type: String +Resources: + S3Bucket: + DeletionPolicy: Retain + Type: AWS::S3::Bucket + Properties: {} + BucketPolicy: + Type: AWS::S3::BucketPolicy + Properties: + Bucket: + Ref: S3Bucket + PolicyDocument: + Version: "2012-10-17" + Statement: + - Sid: "AWSCloudTrailAclCheck" + Effect: "Allow" + Principal: + Service: "cloudtrail.amazonaws.com" + Action: "s3:GetBucketAcl" + Resource: !Sub |- + arn:aws:s3:::${S3Bucket} + - Sid: "AWSCloudTrailWrite" + Effect: "Allow" + Principal: + Service: "cloudtrail.amazonaws.com" + Action: "s3:PutObject" + Resource: !Sub |- + arn:aws:s3:::${S3Bucket}/AWSLogs/${AWS::AccountId}/* + Condition: + StringEquals: + s3:x-amz-acl: "bucket-owner-full-control" + Topic: + Type: AWS::SNS::Topic + Properties: + Subscription: + - Endpoint: + Ref: OperatorEmail + Protocol: email + TopicPolicy: + Type: AWS::SNS::TopicPolicy + Properties: + Topics: + - Ref: "Topic" + PolicyDocument: + Version: "2008-10-17" + Statement: + - Sid: "AWSCloudTrailSNSPolicy" + Effect: "Allow" + Principal: + Service: "cloudtrail.amazonaws.com" + Resource: "*" + Action: "SNS:Publish" + myTrail: + DependsOn: + - BucketPolicy + - TopicPolicy + Type: AWS::CloudTrail::Trail + Properties: + S3BucketName: + Ref: S3Bucket + SnsTopicName: + Fn::GetAtt: + - Topic + - TopicName + IsLogging: true + IsMultiRegionTrail: "false" diff --git a/assets/queries/cloudFormation/aws/cloudtrail_multi_region_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/cloudtrail_multi_region_disabled/test/positive_expected_result.json index 136a82682e8..ed813dff05c 100644 --- a/assets/queries/cloudFormation/aws/cloudtrail_multi_region_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/cloudtrail_multi_region_disabled/test/positive_expected_result.json @@ -1,15 +1,15 @@ [ - { - "line": 70, - "fileName": "positive1.yaml", + { "queryName": "CloudTrail Multi Region Disabled", - "severity": "LOW" + "severity": "LOW", + "line": 70, + "fileName": "positive1.yaml" }, { + "queryName": "CloudTrail Multi Region Disabled", "severity": "LOW", "line": 76, - "fileName": "positive1.yaml", - "queryName": "CloudTrail Multi Region Disabled" + "fileName": "positive1.yaml" }, { "queryName": "CloudTrail Multi Region Disabled", @@ -18,9 +18,15 @@ "fileName": "positive2.json" }, { + "queryName": "CloudTrail Multi Region Disabled", "severity": "LOW", "line": 32, - "fileName": "positive2.json", - "queryName": "CloudTrail Multi Region Disabled" + "fileName": "positive2.json" + }, + { + "queryName": "CloudTrail Multi Region Disabled", + "severity": "LOW", + "line": 70, + "fileName": "positive3.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/cloudwatch_metrics_disabled/query.rego b/assets/queries/cloudFormation/aws/cloudwatch_metrics_disabled/query.rego index dbe40dd211a..57cd5ee200c 100644 --- a/assets/queries/cloudFormation/aws/cloudwatch_metrics_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/cloudwatch_metrics_disabled/query.rego @@ -52,7 +52,7 @@ CxPolicy[result] { methods := resource.Properties.MethodSettings method := methods[idx] - method.MetricsEnabled == "false" + cf_lib.isCloudFormationFalse(method.MetricsEnabled) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/cmk_is_unusable/query.rego b/assets/queries/cloudFormation/aws/cmk_is_unusable/query.rego index 4c158ef5f75..b317293811e 100644 --- a/assets/queries/cloudFormation/aws/cmk_is_unusable/query.rego +++ b/assets/queries/cloudFormation/aws/cmk_is_unusable/query.rego @@ -5,7 +5,7 @@ import data.generic.cloudformation as cf_lib CxPolicy[result] { resource := input.document[i].Resources[name] resource.Type == "AWS::KMS::Key" - resource.Properties.Enabled == false + cf_lib.isCloudFormationFalse(resource.Properties.Enabled) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/cmk_is_unusable/test/negative1.yaml b/assets/queries/cloudFormation/aws/cmk_is_unusable/test/negative1.yaml index d3ceba99887..09e164e891c 100644 --- a/assets/queries/cloudFormation/aws/cmk_is_unusable/test/negative1.yaml +++ b/assets/queries/cloudFormation/aws/cmk_is_unusable/test/negative1.yaml @@ -1,4 +1,3 @@ -#this code is a correct code for which the query should not find any result Resources: myKey: Type: AWS::KMS::Key diff --git a/assets/queries/cloudFormation/aws/cmk_is_unusable/test/negative3.yaml b/assets/queries/cloudFormation/aws/cmk_is_unusable/test/negative3.yaml new file mode 100644 index 00000000000..0de6a4c754e --- /dev/null +++ b/assets/queries/cloudFormation/aws/cmk_is_unusable/test/negative3.yaml @@ -0,0 +1,30 @@ +Resources: + myKey: + Type: AWS::KMS::Key + Properties: + Enabled: "true" + KeyPolicy: + Version: '2012-10-17' + Id: key-default-1 + Statement: + - Sid: Enable IAM User Permissions + Effect: Allow + Principal: + AWS: + Fn::Join: + - '' + - - 'arn:aws:iam::' + - Ref: AWS::AccountId + - :root + Action: kms:* + Resource: '*' + Tags: + - Key: + Ref: Key + Value: + Ref: Value +Parameters: + Key: + Type: String + Value: + Type: String diff --git a/assets/queries/cloudFormation/aws/cmk_is_unusable/test/positive1.yaml b/assets/queries/cloudFormation/aws/cmk_is_unusable/test/positive1.yaml index 9f26612aa9e..a8f61d5361d 100644 --- a/assets/queries/cloudFormation/aws/cmk_is_unusable/test/positive1.yaml +++ b/assets/queries/cloudFormation/aws/cmk_is_unusable/test/positive1.yaml @@ -1,4 +1,3 @@ -#this is a problematic code where the query should report a result(s) Resources: myKey: Type: AWS::KMS::Key diff --git a/assets/queries/cloudFormation/aws/cmk_is_unusable/test/positive3.yaml b/assets/queries/cloudFormation/aws/cmk_is_unusable/test/positive3.yaml new file mode 100644 index 00000000000..4b6559c7806 --- /dev/null +++ b/assets/queries/cloudFormation/aws/cmk_is_unusable/test/positive3.yaml @@ -0,0 +1,30 @@ +Resources: + myKey: + Type: AWS::KMS::Key + Properties: + Enabled: "false" + KeyPolicy: + Version: '2012-10-17' + Id: key-default-1 + Statement: + - Sid: Enable IAM User Permissions + Effect: Allow + Principal: + AWS: + Fn::Join: + - '' + - - 'arn:aws:iam::' + - Ref: AWS::AccountId + - :root + Action: kms:* + Resource: '*' + Tags: + - Key: + Ref: Key + Value: + Ref: Value +Parameters: + Key: + Type: String + Value: + Type: String diff --git a/assets/queries/cloudFormation/aws/cmk_is_unusable/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/cmk_is_unusable/test/positive_expected_result.json index c15d602c1cb..d1b3cd303b5 100644 --- a/assets/queries/cloudFormation/aws/cmk_is_unusable/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/cmk_is_unusable/test/positive_expected_result.json @@ -2,13 +2,13 @@ { "queryName": "CMK Is Unusable", "severity": "MEDIUM", - "line": 6, + "line": 5, "fileName": "positive1.yaml" }, { "queryName": "CMK Is Unusable", "severity": "MEDIUM", - "line": 31, + "line": 30, "fileName": "positive1.yaml" }, { @@ -22,5 +22,11 @@ "severity": "MEDIUM", "line": 59, "fileName": "positive2.json" + }, + { + "queryName": "CMK Is Unusable", + "severity": "MEDIUM", + "line": 5, + "fileName": "positive3.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/cmk_rotation_disabled/query.rego b/assets/queries/cloudFormation/aws/cmk_rotation_disabled/query.rego index 4c7333b12ed..d88fc8f466a 100644 --- a/assets/queries/cloudFormation/aws/cmk_rotation_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/cmk_rotation_disabled/query.rego @@ -6,7 +6,7 @@ import data.generic.cloudformation as cf_lib CxPolicy[result] { resource := input.document[i].Resources[name] resource.Type == "AWS::KMS::Key" - resource.Properties.Enabled == true + cf_lib.isCloudFormationTrue(resource.Properties.Enabled) not common_lib.valid_key(resource.Properties, "PendingWindowInDays") not common_lib.valid_key(resource.Properties, "EnableKeyRotation") @@ -24,9 +24,9 @@ CxPolicy[result] { CxPolicy[result] { resource := input.document[i].Resources[name] resource.Type == "AWS::KMS::Key" - resource.Properties.Enabled == true + cf_lib.isCloudFormationTrue(resource.Properties.Enabled) not common_lib.valid_key(resource.Properties, "PendingWindowInDays") - resource.Properties.EnableKeyRotation == false + cf_lib.isCloudFormationFalse(resource.Properties.EnableKeyRotation) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/cmk_rotation_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/cmk_rotation_disabled/test/negative3.yaml new file mode 100644 index 00000000000..0eed038e079 --- /dev/null +++ b/assets/queries/cloudFormation/aws/cmk_rotation_disabled/test/negative3.yaml @@ -0,0 +1,32 @@ +#this code is a correct code for which the query should not find any result +Resources: + myKey: + Type: AWS::KMS::Key + Properties: + Enabled: "true" + EnableKeyRotation: "true" + KeyPolicy: + Version: '2012-10-17' + Id: key-default-1 + Statement: + - Sid: Enable IAM User Permissions + Effect: Allow + Principal: + AWS: + Fn::Join: + - '' + - - 'arn:aws:iam::' + - Ref: AWS::AccountId + - :root + Action: kms:* + Resource: '*' + Tags: + - Key: + Ref: Key + Value: + Ref: Value +Parameters: + Key: + Type: String + Value: + Type: String \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/cmk_rotation_disabled/test/positive3.yaml b/assets/queries/cloudFormation/aws/cmk_rotation_disabled/test/positive3.yaml new file mode 100644 index 00000000000..ba96bb3ad4b --- /dev/null +++ b/assets/queries/cloudFormation/aws/cmk_rotation_disabled/test/positive3.yaml @@ -0,0 +1,32 @@ +#this is a problematic code where the query should report a result(s) +Resources: + myKey2: + Type: AWS::KMS::Key + Properties: + Enabled: "true" + EnableKeyRotation: "false" + KeyPolicy: + Version: '2012-10-17' + Id: key-default-1 + Statement: + - Sid: Enable IAM User Permissions + Effect: Allow + Principal: + AWS: + Fn::Join: + - '' + - - 'arn:aws:iam::' + - Ref: AWS::AccountId + - :root + Action: kms:* + Resource: '*' + Tags: + - Key: + Ref: Key + Value: + Ref: Value +Parameters: + Key: + Type: String + Value: + Type: String \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/cmk_rotation_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/cmk_rotation_disabled/test/positive_expected_result.json index d7a8b5a42a1..5ebce8e3f8f 100644 --- a/assets/queries/cloudFormation/aws/cmk_rotation_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/cmk_rotation_disabled/test/positive_expected_result.json @@ -6,21 +6,27 @@ "fileName": "positive1.yaml" }, { - "fileName": "positive1.yaml", "queryName": "CMK Rotation Disabled", "severity": "LOW", - "line": 31 + "line": 31, + "fileName": "positive1.yaml" }, { - "fileName": "positive2.json", "queryName": "CMK Rotation Disabled", "severity": "LOW", - "line": 5 + "line": 5, + "fileName": "positive2.json" }, { "queryName": "CMK Rotation Disabled", "severity": "LOW", "line": 49, "fileName": "positive2.json" + }, + { + "queryName": "CMK Rotation Disabled", + "severity": "LOW", + "line": 7, + "fileName": "positive3.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/config_configuration_aggregator_to_all_regions_disabled/query.rego b/assets/queries/cloudFormation/aws/config_configuration_aggregator_to_all_regions_disabled/query.rego index b432c527197..e0ae8e64f76 100644 --- a/assets/queries/cloudFormation/aws/config_configuration_aggregator_to_all_regions_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/config_configuration_aggregator_to_all_regions_disabled/query.rego @@ -45,7 +45,7 @@ CxPolicy[result] { accSources := resource.Properties.AccountAggregationSources - accSources[j].AllAwsRegions == false + cf_lib.isCloudFormationFalse(accSources[j].AllAwsRegions) result := { "documentId": input.document[i].id, @@ -83,7 +83,7 @@ CxPolicy[result] { orgSource := resource.Properties.OrganizationAggregationSource - orgSource.AllAwsRegions == false + cf_lib.isCloudFormationFalse(orgSource.AllAwsRegions) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/config_configuration_aggregator_to_all_regions_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/config_configuration_aggregator_to_all_regions_disabled/test/negative3.yaml new file mode 100644 index 00000000000..b6b79e6b841 --- /dev/null +++ b/assets/queries/cloudFormation/aws/config_configuration_aggregator_to_all_regions_disabled/test/negative3.yaml @@ -0,0 +1,24 @@ +Resources: + ConfigurationAggregator9: + Type: 'AWS::Config::ConfigurationAggregator' + Properties: + AccountAggregationSources: + - AccountIds: + - '123456789012' + - '987654321012' + AwsRegions: + - us-west-2 + - us-east-1 + AllAwsRegions: "true" + ConfigurationAggregatorName: MyConfigurationAggregator + ConfigurationAggregator10: + Type: 'AWS::Config::ConfigurationAggregator' + Properties: + OrganizationAggregationSource: + RoleArn: >- + arn:aws:iam::012345678912:role/aws-service-role/organizations.amazonaws.com/AWSServiceRoleForOrganizations + AwsRegions: + - us-west-2 + - us-east-1 + AllAwsRegions: "true" + ConfigurationAggregatorName: MyConfigurationAggregator diff --git a/assets/queries/cloudFormation/aws/config_configuration_aggregator_to_all_regions_disabled/test/positive3.yaml b/assets/queries/cloudFormation/aws/config_configuration_aggregator_to_all_regions_disabled/test/positive3.yaml new file mode 100644 index 00000000000..87b08cb3115 --- /dev/null +++ b/assets/queries/cloudFormation/aws/config_configuration_aggregator_to_all_regions_disabled/test/positive3.yaml @@ -0,0 +1,18 @@ +AWSTemplateFormatVersion: "2010-09-09" +Parameters: + OperatorEmail: + Description: "Email address to notify when new logs are published." + Type: String +Resources: + ConfigurationAggregator2: + Type: 'AWS::Config::ConfigurationAggregator' + Properties: + AccountAggregationSources: + - AccountIds: + - '123456789012' + - '987654321012' + AwsRegions: + - us-west-2 + - us-east-1 + AllAwsRegions: "false" + ConfigurationAggregatorName: MyConfigurationAggregator diff --git a/assets/queries/cloudFormation/aws/config_configuration_aggregator_to_all_regions_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/config_configuration_aggregator_to_all_regions_disabled/test/positive_expected_result.json index 8bd33bbad86..2a915ae18e2 100644 --- a/assets/queries/cloudFormation/aws/config_configuration_aggregator_to_all_regions_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/config_configuration_aggregator_to_all_regions_disabled/test/positive_expected_result.json @@ -46,5 +46,11 @@ "severity": "LOW", "line": 62, "fileName": "positive2.json" - } + }, + { + "queryName": "Configuration Aggregator to All Regions Disabled", + "severity": "LOW", + "line": 10, + "fileName": "positive3.yaml" + }, ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/db_security_group_with_public_scope/query.rego b/assets/queries/cloudFormation/aws/db_security_group_with_public_scope/query.rego index 9c6c2f6941a..740298f4a7a 100644 --- a/assets/queries/cloudFormation/aws/db_security_group_with_public_scope/query.rego +++ b/assets/queries/cloudFormation/aws/db_security_group_with_public_scope/query.rego @@ -69,5 +69,5 @@ CxPolicy[result] { check_public(resource) { resource.Type == "AWS::RDS::DBInstance" - resource.Properties.PubliclyAccessible == true + cf_lib.isCloudFormationTrue(resource.Properties.PubliclyAccessible) } diff --git a/assets/queries/cloudFormation/aws/db_security_group_with_public_scope/test/negative5.yaml b/assets/queries/cloudFormation/aws/db_security_group_with_public_scope/test/negative5.yaml new file mode 100644 index 00000000000..ce069935ae2 --- /dev/null +++ b/assets/queries/cloudFormation/aws/db_security_group_with_public_scope/test/negative5.yaml @@ -0,0 +1,40 @@ +#this code is a correct code for which the query should not find any result +Resources: + DBEC2SecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Open database for access + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: 1.2.3.4/24 + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIpv6: 2001:0db8:85a3:0000:0000:8a2e:0370:7334 + SecurityGroupEgress: + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: 0.0.0.0/0 + DBInstance: + Type: AWS::RDS::DBInstance + Properties: + PubliclyAccessible: "true" + DBName: + Ref: DBName + Engine: MySQL + MultiAZ: + Ref: MultiAZDatabase + MasterUsername: + Ref: DBUser + DBInstanceClass: + Ref: DBClass + AllocatedStorage: + Ref: DBAllocatedStorage + MasterUserPassword: + Ref: DBPassword + VPCSecurityGroups: + - !GetAtt DBEC2SecurityGroup.GroupId + diff --git a/assets/queries/cloudFormation/aws/db_security_group_with_public_scope/test/positive7.yaml b/assets/queries/cloudFormation/aws/db_security_group_with_public_scope/test/positive7.yaml new file mode 100644 index 00000000000..6b49de96255 --- /dev/null +++ b/assets/queries/cloudFormation/aws/db_security_group_with_public_scope/test/positive7.yaml @@ -0,0 +1,34 @@ +Resources: + DBEC2SecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Open database for access + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: 0.0.0.0/0 + SecurityGroupEgress: + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: 0.0.0.0/0 + DBInstance: + Type: AWS::RDS::DBInstance + Properties: + PubliclyAccessible: "true" + DBName: + Ref: DBName + Engine: MySQL + MultiAZ: + Ref: MultiAZDatabase + MasterUsername: + Ref: DBUser + DBInstanceClass: + Ref: DBClass + AllocatedStorage: + Ref: DBAllocatedStorage + MasterUserPassword: + Ref: DBPassword + VPCSecurityGroups: + - !GetAtt DBEC2SecurityGroup.GroupId diff --git a/assets/queries/cloudFormation/aws/db_security_group_with_public_scope/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/db_security_group_with_public_scope/test/positive_expected_result.json index 8eeea186111..813178a1c95 100644 --- a/assets/queries/cloudFormation/aws/db_security_group_with_public_scope/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/db_security_group_with_public_scope/test/positive_expected_result.json @@ -1,21 +1,21 @@ [ { + "queryName": "DB Security Group With Public Scope", "severity": "CRITICAL", "line": 6, - "fileName": "positive1.yaml", - "queryName": "DB Security Group With Public Scope" + "fileName": "positive1.yaml" }, { "queryName": "DB Security Group With Public Scope", "severity": "CRITICAL", - "line": 6, - "fileName": "positive3.yaml" + "line": 19, + "fileName": "positive2.yaml" }, { "queryName": "DB Security Group With Public Scope", "severity": "CRITICAL", - "line": 19, - "fileName": "positive2.yaml" + "line": 6, + "fileName": "positive3.yaml" }, { "queryName": "DB Security Group With Public Scope", @@ -30,9 +30,15 @@ "fileName": "positive5.json" }, { + "queryName": "DB Security Group With Public Scope", + "severity": "CRITICAL", "line": 15, - "fileName": "positive6.json", + "fileName": "positive6.json" + }, + { "queryName": "DB Security Group With Public Scope", - "severity": "CRITICAL" + "severity": "CRITICAL", + "line": 6, + "fileName": "positive7.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/default_kms_key_usage/query.rego b/assets/queries/cloudFormation/aws/default_kms_key_usage/query.rego index 64aecf6e65d..e812899ac0f 100644 --- a/assets/queries/cloudFormation/aws/default_kms_key_usage/query.rego +++ b/assets/queries/cloudFormation/aws/default_kms_key_usage/query.rego @@ -9,7 +9,7 @@ CxPolicy[result] { common_lib.inArray({"AWS::DocDB::DBCluster", "AWS::Neptune::DBCluster", "AWS::RDS::DBCluster", "AWS::RDS::DBInstance", "AWS::Redshift::Cluster"}, resource.Type) properties := resource.Properties - properties.StorageEncrypted == true + cf_lib.isCloudFormationTrue(properties.StorageEncrypted) not common_lib.valid_key(properties, "KmsKeyId") result := { diff --git a/assets/queries/cloudFormation/aws/default_kms_key_usage/test/negative3.yaml b/assets/queries/cloudFormation/aws/default_kms_key_usage/test/negative3.yaml new file mode 100644 index 00000000000..c73bac54f67 --- /dev/null +++ b/assets/queries/cloudFormation/aws/default_kms_key_usage/test/negative3.yaml @@ -0,0 +1,36 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: RDS Storage Encrypted +Parameters: + SourceDBInstanceIdentifier: + Type: String + DBInstanceType: + Type: String + SourceRegion: + Type: String +Resources: + MyKey: + Type: "AWS::KMS::Key" + Properties: + KeyPolicy: + Version: 2012-10-17 + Id: key-default-1 + Statement: + - Sid: Enable IAM User Permissions + Effect: Allow + Principal: + AWS: !Join + - "" + - - "arn:aws:iam::" + - !Ref "AWS::AccountId" + - ":root" + Action: "kms:*" + Resource: "*" + MyDBSmall: + Type: "AWS::RDS::DBInstance" + Properties: + DBInstanceClass: !Ref DBInstanceType + SourceDBInstanceIdentifier: !Ref SourceDBInstanceIdentifier + SourceRegion: !Ref SourceRegion + KmsKeyId: !Ref MyKey + StorageEncrypted: "true" + diff --git a/assets/queries/cloudFormation/aws/default_kms_key_usage/test/positive3.yaml b/assets/queries/cloudFormation/aws/default_kms_key_usage/test/positive3.yaml new file mode 100644 index 00000000000..b10771083e2 --- /dev/null +++ b/assets/queries/cloudFormation/aws/default_kms_key_usage/test/positive3.yaml @@ -0,0 +1,36 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: >- + AWS CloudFormation Sample Template +Parameters: + DBUsername: + NoEcho: 'true' + Description: Username for MySQL database access + Type: String + MinLength: '1' + MaxLength: '16' + AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*' + ConstraintDescription: must begin with a letter and contain only alphanumeric characters. + DBPassword: + NoEcho: 'true' + Description: Password MySQL database access + Type: String + MinLength: '8' + MaxLength: '41' + AllowedPattern: '[a-zA-Z0-9]*' + ConstraintDescription: must contain only alphanumeric characters. +Resources: + RDSCluster1: + Type: 'AWS::RDS::DBCluster' + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + DBClusterIdentifier: my-serverless-cluster + Engine: aurora + EngineVersion: 5.6.10a + EngineMode: serverless + ScalingConfiguration: + AutoPause: "true" + MinCapacity: 4 + MaxCapacity: 32 + SecondsUntilAutoPause: 1000 + StorageEncrypted: "true" diff --git a/assets/queries/cloudFormation/aws/default_kms_key_usage/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/default_kms_key_usage/test/positive_expected_result.json index add1513bb2e..4df0f766fc8 100644 --- a/assets/queries/cloudFormation/aws/default_kms_key_usage/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/default_kms_key_usage/test/positive_expected_result.json @@ -10,5 +10,11 @@ "severity": "MEDIUM", "line": 25, "fileName": "positive2.json" + }, + { + "queryName": "Default KMS Key Usage", + "severity": "MEDIUM", + "line": 24, + "fileName": "positive3.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/dynamodb_table_not_encrypted/query.rego b/assets/queries/cloudFormation/aws/dynamodb_table_not_encrypted/query.rego index 547ab87abbc..9dcbac41f32 100644 --- a/assets/queries/cloudFormation/aws/dynamodb_table_not_encrypted/query.rego +++ b/assets/queries/cloudFormation/aws/dynamodb_table_not_encrypted/query.rego @@ -8,7 +8,7 @@ CxPolicy[result] { resource := document.Resources[key] resource.Type == "AWS::DynamoDB::Table" properties := resource.Properties - properties.SSESpecification.SSEEnabled == false + cf_lib.isCloudFormationFalse(properties.SSESpecification.SSEEnabled) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/dynamodb_table_not_encrypted/test/positive3.yml b/assets/queries/cloudFormation/aws/dynamodb_table_not_encrypted/test/positive3.yml new file mode 100644 index 00000000000..ad6ffc54999 --- /dev/null +++ b/assets/queries/cloudFormation/aws/dynamodb_table_not_encrypted/test/positive3.yml @@ -0,0 +1,55 @@ +AWSTemplateFormatVersion: 2010-09-09 +Resources: + OrdersTable: + Type: AWS::DynamoDB::Table + Properties: + TableName: AuthorsTable_prod + SSESpecification: + SSEEnabled: "false" + AttributeDefinitions: + - AttributeName: "AuthorName" + AttributeType: "S" + - AttributeName: "BookTitle" + AttributeType: "S" + KeySchema: + - AttributeName: "AuthorName" + KeyType: "HASH" + - AttributeName: "BookTitle" + KeyType: "RANGE" + TimeToLiveSpecification: + AttributeName: "ExpirationTime" + Enabled: true + ProvisionedThroughput: + ReadCapacityUnits: "10" + WriteCapacityUnits: "5" + DependsOn: + - DynamoDBQueryPolicy + + DynamoDBQueryPolicy: + Type: "AWS::IAM::Policy" + Properties: + PolicyName: DynamoDBQueryPolicy + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Action: "dynamodb:Query" + Resource: "*" + Roles: + - Ref: "OrdersTableQueryRole" + + OrdersTableQueryRole: + Type: "AWS::IAM::Role" + Properties: + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Principal: + Service: + - "dynamodb.amazonaws.com" + Action: + - "sts:AssumeRole" + Path: "/" + + diff --git a/assets/queries/cloudFormation/aws/dynamodb_table_not_encrypted/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/dynamodb_table_not_encrypted/test/positive_expected_result.json index 962480b72f8..ca734781071 100644 --- a/assets/queries/cloudFormation/aws/dynamodb_table_not_encrypted/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/dynamodb_table_not_encrypted/test/positive_expected_result.json @@ -10,5 +10,11 @@ "severity": "HIGH", "line": 17, "filename": "positive2.yaml" + }, + { + "queryName": "DynamoDB Table Not Encrypted", + "severity": "HIGH", + "line": 8, + "filename": "positive3.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/query.rego b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/query.rego index 5ac17c30751..9abb3fb2ef4 100644 --- a/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/query.rego @@ -9,7 +9,7 @@ CxPolicy[result] { resource.Type == "AWS::DynamoDB::Table" properties := resource.Properties - properties.PointInTimeRecoverySpecification.PointInTimeRecoveryEnabled == false + cf_lib.isCloudFormationFalse(properties.PointInTimeRecoverySpecification.PointInTimeRecoveryEnabled) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/negative3.yaml new file mode 100644 index 00000000000..4c2d3226586 --- /dev/null +++ b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/negative3.yaml @@ -0,0 +1,6 @@ +Resources: + MyDynamoDBTable: + Type: AWS::DynamoDB::Table + Properties: + PointInTimeRecoverySpecification: + PointInTimeRecoveryEnabled: "true" diff --git a/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive7.yaml b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive7.yaml new file mode 100644 index 00000000000..5588f12265f --- /dev/null +++ b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive7.yaml @@ -0,0 +1,6 @@ +Resources: + MyDynamoDBTable: + Type: AWS::DynamoDB::Table + Properties: + PointInTimeRecoverySpecification: + PointInTimeRecoveryEnabled: "false" diff --git a/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive_expected_result.json index a0a74b5bdfa..09b3e9025e7 100644 --- a/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/dynamodb_table_point_in_time_recovery_disabled/test/positive_expected_result.json @@ -34,5 +34,11 @@ "severity": "MEDIUM", "line": 7, "filename": "positive6.json" + }, + { + "queryName": "DynamoDB Table Point In Time Recovery Disabled", + "severity": "MEDIUM", + "line": 6, + "filename": "positive7.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/query.rego b/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/query.rego index 4d1f11986e5..ac3d8c1111a 100644 --- a/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/query.rego +++ b/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/query.rego @@ -9,7 +9,7 @@ CxPolicy[result] { resource.Type == "AWS::DynamoDB::Table" properties := resource.Properties properties.SSESpecification.SSEType == "KMS" - properties.SSESpecification.SSEEnabled == false + cf_lib.isCloudFormationFalse(properties.SSESpecification.SSEEnabled) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive4.yaml b/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive2.yaml similarity index 100% rename from assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive4.yaml rename to assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive2.yaml diff --git a/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive7.json b/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive4.json similarity index 71% rename from assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive7.json rename to assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive4.json index bd994bb55f6..9ed651ed3a8 100644 --- a/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive7.json +++ b/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive4.json @@ -1,13 +1,11 @@ { + "AWSTemplateFormatVersion": "2010-09-09", "Description": "Sample CloudFormation template for DynamoDB with AWS-Owned CMK", "Resources": { - "DynamoDBOnDemandTable4": { + "DynamoDBOnDemandTable2": { "Type": "AWS::DynamoDB::Table", "Properties": { - "SSESpecification": { - "SSEType": "KMS" - }, - "TableName": "dynamodb-kms-2", + "TableName": "dynamodb-kms-0", "AttributeDefinitions": [ { "AttributeName": "pk", @@ -20,9 +18,12 @@ "KeyType": "HASH" } ], - "BillingMode": "PAY_PER_REQUEST" + "BillingMode": "PAY_PER_REQUEST", + "SSESpecification": { + "SSEEnabled": false, + "SSEType": "KMS" + } } } - }, - "AWSTemplateFormatVersion": "2010-09-11" + } } diff --git a/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive5.json b/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive5.json index 9ed651ed3a8..bd994bb55f6 100644 --- a/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive5.json +++ b/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive5.json @@ -1,11 +1,13 @@ { - "AWSTemplateFormatVersion": "2010-09-09", "Description": "Sample CloudFormation template for DynamoDB with AWS-Owned CMK", "Resources": { - "DynamoDBOnDemandTable2": { + "DynamoDBOnDemandTable4": { "Type": "AWS::DynamoDB::Table", "Properties": { - "TableName": "dynamodb-kms-0", + "SSESpecification": { + "SSEType": "KMS" + }, + "TableName": "dynamodb-kms-2", "AttributeDefinitions": [ { "AttributeName": "pk", @@ -18,12 +20,9 @@ "KeyType": "HASH" } ], - "BillingMode": "PAY_PER_REQUEST", - "SSESpecification": { - "SSEEnabled": false, - "SSEType": "KMS" - } + "BillingMode": "PAY_PER_REQUEST" } } - } + }, + "AWSTemplateFormatVersion": "2010-09-11" } diff --git a/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive8.json b/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive6.json similarity index 100% rename from assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive8.json rename to assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive6.json diff --git a/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive7.yaml b/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive7.yaml new file mode 100644 index 00000000000..93a55613b61 --- /dev/null +++ b/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive7.yaml @@ -0,0 +1,17 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: Sample CloudFormation template for DynamoDB with AWS-Owned CMK +Resources: + DynamoDBOnDemandTable2: + Type: "AWS::DynamoDB::Table" + Properties: + TableName: "dynamodb-kms-0" + AttributeDefinitions: + - AttributeName: pk + AttributeType: S + KeySchema: + - AttributeName: pk + KeyType: HASH + BillingMode: PAY_PER_REQUEST + SSESpecification: + SSEEnabled: "false" + SSEType: "KMS" diff --git a/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive_expected_result.json index 64b2ed4176f..9e900553ca0 100644 --- a/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/dynamodb_with_aws_owned_cmk/test/positive_expected_result.json @@ -1,15 +1,15 @@ [ { - "line": 4, - "fileName": "positive1.yaml", "queryName": "DynamoDB With Aws Owned CMK", - "severity": "HIGH" + "severity": "HIGH", + "line": 4, + "fileName": "positive1.yaml" }, { - "line": 4, - "fileName": "positive4.yaml", "queryName": "DynamoDB With Aws Owned CMK", - "severity": "HIGH" + "severity": "HIGH", + "line": 4, + "fileName": "positive2.yaml" }, { "queryName": "DynamoDB With Aws Owned CMK", @@ -21,18 +21,24 @@ "queryName": "DynamoDB With Aws Owned CMK", "severity": "HIGH", "line": 5, - "fileName": "positive5.json" + "fileName": "positive4.json" }, { + "queryName": "DynamoDB With Aws Owned CMK", "severity": "HIGH", "line": 4, - "fileName": "positive7.json", - "queryName": "DynamoDB With Aws Owned CMK" + "fileName": "positive5.json" }, { "queryName": "DynamoDB With Aws Owned CMK", "severity": "HIGH", "line": 5, - "fileName": "positive8.json" + "fileName": "positive6.json" + }, + { + "queryName": "DynamoDB With Aws Owned CMK", + "severity": "HIGH", + "line": 4, + "fileName": "positive7.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/ebs_volume_encryption_disabled/query.rego b/assets/queries/cloudFormation/aws/ebs_volume_encryption_disabled/query.rego index 0d62705ec63..bb8898e2411 100644 --- a/assets/queries/cloudFormation/aws/ebs_volume_encryption_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/ebs_volume_encryption_disabled/query.rego @@ -26,7 +26,7 @@ CxPolicy[result] { resource = document[i].Resources[name] resource.Type == "AWS::EC2::Volume" properties := resource.Properties - properties.Encrypted == false + cf_lib.isCloudFormationFalse(properties.Encrypted) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/ebs_volume_encryption_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/ebs_volume_encryption_disabled/test/negative3.yaml new file mode 100644 index 00000000000..58ba813c4c4 --- /dev/null +++ b/assets/queries/cloudFormation/aws/ebs_volume_encryption_disabled/test/negative3.yaml @@ -0,0 +1,13 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "Volume" +Resources: + NewVolume: + Type: AWS::EC2::Volume + Properties: + Size: 100 + Encrypted: "true" + AvailabilityZone: !GetAtt Ec2Instance.AvailabilityZone + Tags: + - Key: MyTag + Value: TagValue + DeletionPolicy: Snapshot diff --git a/assets/queries/cloudFormation/aws/ebs_volume_encryption_disabled/test/positive5.yaml b/assets/queries/cloudFormation/aws/ebs_volume_encryption_disabled/test/positive5.yaml new file mode 100644 index 00000000000..f19ca631c9f --- /dev/null +++ b/assets/queries/cloudFormation/aws/ebs_volume_encryption_disabled/test/positive5.yaml @@ -0,0 +1,14 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "Volume" +Resources: + NewVolume: + Type: AWS::EC2::Volume + Properties: + Size: 100 + Encrypted: "false" + AvailabilityZone: !GetAtt Ec2Instance.AvailabilityZone + Tags: + - Key: MyTag + Value: TagValue + DeletionPolicy: Snapshot + diff --git a/assets/queries/cloudFormation/aws/ebs_volume_encryption_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/ebs_volume_encryption_disabled/test/positive_expected_result.json index 598107a6aaf..79ec37039ae 100644 --- a/assets/queries/cloudFormation/aws/ebs_volume_encryption_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/ebs_volume_encryption_disabled/test/positive_expected_result.json @@ -2,14 +2,14 @@ { "queryName": "EBS Volume Encryption Disabled", "severity": "HIGH", - "line": 6, - "fileName": "positive2.yaml" + "line": 8, + "fileName": "positive1.yaml" }, { "queryName": "EBS Volume Encryption Disabled", "severity": "HIGH", - "line": 8, - "fileName": "positive1.yaml" + "line": 6, + "fileName": "positive2.yaml" }, { "queryName": "EBS Volume Encryption Disabled", @@ -22,5 +22,11 @@ "severity": "HIGH", "line": 6, "fileName": "positive4.json" + }, + { + "queryName": "EBS Volume Encryption Disabled", + "severity": "HIGH", + "line": 8, + "fileName": "positive5.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/ec2_instance_monitoring_disabled/query.rego b/assets/queries/cloudFormation/aws/ec2_instance_monitoring_disabled/query.rego index aaa9c7994ab..617df8bc0ee 100644 --- a/assets/queries/cloudFormation/aws/ec2_instance_monitoring_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/ec2_instance_monitoring_disabled/query.rego @@ -8,7 +8,7 @@ CxPolicy[result] { resource := doc[name] resource.Type == "AWS::EC2::Instance" - resource.Properties.Monitoring == false + cf_lib.isCloudFormationFalse(resource.Properties.Monitoring) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/ec2_instance_monitoring_disabled/test/negative2.yaml b/assets/queries/cloudFormation/aws/ec2_instance_monitoring_disabled/test/negative2.yaml new file mode 100644 index 00000000000..ce137f47669 --- /dev/null +++ b/assets/queries/cloudFormation/aws/ec2_instance_monitoring_disabled/test/negative2.yaml @@ -0,0 +1,7 @@ +Resources: + MyEC2Instance: + Type: AWS::EC2::Instance + Properties: + ImageId: ami-12345678 + InstanceType: t2.micro + Monitoring: "true" diff --git a/assets/queries/cloudFormation/aws/ec2_instance_monitoring_disabled/test/positive3.yaml b/assets/queries/cloudFormation/aws/ec2_instance_monitoring_disabled/test/positive3.yaml new file mode 100644 index 00000000000..149afff8bab --- /dev/null +++ b/assets/queries/cloudFormation/aws/ec2_instance_monitoring_disabled/test/positive3.yaml @@ -0,0 +1,7 @@ +Resources: + MyEC2Instance: + Type: AWS::EC2::Instance + Properties: + ImageId: ami-12345678 + InstanceType: t2.micro + Monitoring: "false" diff --git a/assets/queries/cloudFormation/aws/ec2_instance_monitoring_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/ec2_instance_monitoring_disabled/test/positive_expected_result.json index 106fefb6f4e..98e34e6fa58 100644 --- a/assets/queries/cloudFormation/aws/ec2_instance_monitoring_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/ec2_instance_monitoring_disabled/test/positive_expected_result.json @@ -10,5 +10,11 @@ "severity": "MEDIUM", "line": 4, "fileName": "positive2.yaml" + }, + { + "queryName": "EC2 Instance Monitoring Disabled", + "severity": "MEDIUM", + "line": 7, + "fileName": "positive3.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/ec2_instance_subnet_has_public_ip_mapping_on_launch/query.rego b/assets/queries/cloudFormation/aws/ec2_instance_subnet_has_public_ip_mapping_on_launch/query.rego index e149cf87c0f..4e5526795d4 100644 --- a/assets/queries/cloudFormation/aws/ec2_instance_subnet_has_public_ip_mapping_on_launch/query.rego +++ b/assets/queries/cloudFormation/aws/ec2_instance_subnet_has_public_ip_mapping_on_launch/query.rego @@ -7,7 +7,7 @@ CxPolicy[result] { [path, Resources] := walk(docs) resource := Resources[name] resource.Type == "AWS::EC2::Subnet" - resource.Properties.MapPublicIpOnLaunch == true + cf_lib.isCloudFormationTrue(resource.Properties.MapPublicIpOnLaunch) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/ec2_instance_subnet_has_public_ip_mapping_on_launch/test/negative3.yaml b/assets/queries/cloudFormation/aws/ec2_instance_subnet_has_public_ip_mapping_on_launch/test/negative3.yaml new file mode 100644 index 00000000000..5ae1f6e4cb5 --- /dev/null +++ b/assets/queries/cloudFormation/aws/ec2_instance_subnet_has_public_ip_mapping_on_launch/test/negative3.yaml @@ -0,0 +1,13 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: A sample template +Resources: + mySubnet: + Type: AWS::EC2::Subnet + Properties: + MapPublicIpOnLaunch: "false" + VpcId: myVPC + CidrBlock: 10.0.0.0/24 + AvailabilityZone: "us-east-1a" + Tags: + - Key: foo + Value: bar diff --git a/assets/queries/cloudFormation/aws/ec2_instance_subnet_has_public_ip_mapping_on_launch/test/positive3.yaml b/assets/queries/cloudFormation/aws/ec2_instance_subnet_has_public_ip_mapping_on_launch/test/positive3.yaml new file mode 100644 index 00000000000..554a72695af --- /dev/null +++ b/assets/queries/cloudFormation/aws/ec2_instance_subnet_has_public_ip_mapping_on_launch/test/positive3.yaml @@ -0,0 +1,13 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: A sample template +Resources: + mySubnet: + Type: AWS::EC2::Subnet + Properties: + MapPublicIpOnLaunch: "true" + VpcId: myVPC + CidrBlock: 10.0.0.0/24 + AvailabilityZone: "us-east-1a" + Tags: + - Key: foo + Value: bar diff --git a/assets/queries/cloudFormation/aws/ec2_instance_subnet_has_public_ip_mapping_on_launch/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/ec2_instance_subnet_has_public_ip_mapping_on_launch/test/positive_expected_result.json index d1d6f013930..95bff5b59c4 100644 --- a/assets/queries/cloudFormation/aws/ec2_instance_subnet_has_public_ip_mapping_on_launch/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/ec2_instance_subnet_has_public_ip_mapping_on_launch/test/positive_expected_result.json @@ -10,5 +10,11 @@ "severity": "MEDIUM", "line": 8, "fileName": "positive2.json" + }, + { + "queryName": "EC2 Instance Subnet Has Public IP Mapping On Launch", + "severity": "MEDIUM", + "line": 7, + "fileName": "positive3.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/ec2_not_ebs_optimized/query.rego b/assets/queries/cloudFormation/aws/ec2_not_ebs_optimized/query.rego index db4ad12b1a1..57e8468095d 100644 --- a/assets/queries/cloudFormation/aws/ec2_not_ebs_optimized/query.rego +++ b/assets/queries/cloudFormation/aws/ec2_not_ebs_optimized/query.rego @@ -26,7 +26,7 @@ CxPolicy[result] { resource := input.document[i].Resources[name] resource.Type == "AWS::EC2::Instance" - resource.Properties.EbsOptimized == false + cf_lib.isCloudFormationFalse(resource.Properties.EbsOptimized) instanceType := get_instance_type(resource.Properties) not common_lib.is_aws_ebs_optimized_by_default(instanceType) diff --git a/assets/queries/cloudFormation/aws/ec2_not_ebs_optimized/test/negative5.yaml b/assets/queries/cloudFormation/aws/ec2_not_ebs_optimized/test/negative5.yaml new file mode 100644 index 00000000000..17680f6d4f9 --- /dev/null +++ b/assets/queries/cloudFormation/aws/ec2_not_ebs_optimized/test/negative5.yaml @@ -0,0 +1,16 @@ +Resources: + MyEC2Instance: + Type: AWS::EC2::Instance + Properties: + ImageId: "ami-79fd7eee" + KeyName: "testkey" + BlockDeviceMappings: + - DeviceName: "/dev/sdm" + Ebs: + VolumeType: "io1" + Iops: "200" + DeleteOnTermination: "false" + VolumeSize: "20" + - DeviceName: "/dev/sdk" + NoDevice: {} + EbsOptimized: "true" diff --git a/assets/queries/cloudFormation/aws/ec2_not_ebs_optimized/test/positive7.yaml b/assets/queries/cloudFormation/aws/ec2_not_ebs_optimized/test/positive7.yaml new file mode 100644 index 00000000000..f4239cdc7d4 --- /dev/null +++ b/assets/queries/cloudFormation/aws/ec2_not_ebs_optimized/test/positive7.yaml @@ -0,0 +1,16 @@ +Resources: + MyEC2Instance: + Type: AWS::EC2::Instance + Properties: + ImageId: "ami-79fd7eee" + KeyName: "testkey" + BlockDeviceMappings: + - DeviceName: "/dev/sdm" + Ebs: + VolumeType: "io1" + Iops: "200" + DeleteOnTermination: "false" + VolumeSize: "20" + - DeviceName: "/dev/sdk" + NoDevice: {} + EbsOptimized: "false" diff --git a/assets/queries/cloudFormation/aws/ec2_not_ebs_optimized/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/ec2_not_ebs_optimized/test/positive_expected_result.json index ed0f01923e9..53aad6fca47 100644 --- a/assets/queries/cloudFormation/aws/ec2_not_ebs_optimized/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/ec2_not_ebs_optimized/test/positive_expected_result.json @@ -34,5 +34,11 @@ "severity": "INFO", "line": 5, "fileName": "positive6.json" + }, + { + "queryName": "EC2 Not EBS Optimized", + "severity": "INFO", + "line": 16, + "fileName": "positive7.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/efs_not_encrypted/query.rego b/assets/queries/cloudFormation/aws/efs_not_encrypted/query.rego index 6b2fd3503a8..6de52d7e0dd 100644 --- a/assets/queries/cloudFormation/aws/efs_not_encrypted/query.rego +++ b/assets/queries/cloudFormation/aws/efs_not_encrypted/query.rego @@ -7,7 +7,7 @@ CxPolicy[result] { resource = document.Resources[key] resource.Type == "AWS::EFS::FileSystem" properties := resource.Properties - properties.Encrypted == false + cf_lib.isCloudFormationFalse(properties.Encrypted) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/efs_not_encrypted/test/negative3.yaml b/assets/queries/cloudFormation/aws/efs_not_encrypted/test/negative3.yaml new file mode 100644 index 00000000000..dd4919a0008 --- /dev/null +++ b/assets/queries/cloudFormation/aws/efs_not_encrypted/test/negative3.yaml @@ -0,0 +1,108 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "Create EFS system and Mount Targets for test VPC" +Parameters: + VPC: + Type: String + Description: The VPC identity + Default: vpc-ID + SubnetID1: + Type: String + Description: The subnet where to launch the service + Default: subnet-ID + SubnetID2: + Type: String + Description: the subnet where to Launch the service + Default: subnet-ID + SubnetID3: + Type: String + Description: The subnet where to launch the service + Default: subnet-ID + SubnetID4: + Type: String + Description: the subnet where to Launch the service + Default: subnet-ID +Resources: + EFSSecurityGroup: + Type: "AWS::EC2::SecurityGroup" + Properties: + GroupDescription: "security group for the prod EFS" + GroupName: "test-EFS-SG" + VpcId: !Ref VPC + SecurityGroupIngress: + - SourceSecurityGroupId: sg-ID + Description: "servers to connect to efs" + FromPort: 2049 + IpProtocol: "tcp" + ToPort: 2049 + Tags: + - Key: Environment + Value: prod + - Key: Name + Value: test-VPC-EFS-SG + - Key: Project + Value: ITEngineering + EFSFileSystem: + Type: AWS::EFS::FileSystem + Properties: + BackupPolicy: + Status: ENABLED + Encrypted: "true" + LifecyclePolicies: + - TransitionToIA: AFTER_60_DAYS + PerformanceMode: generalPurpose + ThroughputMode: bursting + FileSystemTags: + - Key: Environment + Value: prod + - Key: Name + Value: test-VPC-EFS + - Key: Project + Value: ITEngineering + MountTarget1: + Type: AWS::EFS::MountTarget + Properties: + FileSystemId: !Ref EFSFileSystem + IpAddress: "*.*.*.*" + SecurityGroups: + - !Ref EFSSecurityGroup + SubnetId: !Ref SubnetID1 + MountTarget2: + Type: AWS::EFS::MountTarget + Properties: + FileSystemId: !Ref EFSFileSystem + IpAddress: "*.*.*.*" + SecurityGroups: + - !Ref EFSSecurityGroup + SubnetId: !Ref SubnetID2 + MountTarget3: + Type: AWS::EFS::MountTarget + Properties: + FileSystemId: !Ref EFSFileSystem + IpAddress: "*.*.*.*" + SecurityGroups: + - !Ref EFSSecurityGroup + SubnetId: !Ref SubnetID3 + MountTarget4: + Type: AWS::EFS::MountTarget + Properties: + FileSystemId: !Ref EFSFileSystem + IpAddress: "*.*.*.*" + SecurityGroups: + - !Ref EFSSecurityGroup + SubnetId: !Ref SubnetID4 +Outputs: + EFS: + Description: The created EFS + Value: !Ref EFSFileSystem + EFSMountTarget1: + Description: The EFS MountTarget1 + Value: !Ref MountTarget1 + EFSMountTarget2: + Description: The EFS MountTarget2 + Value: !Ref MountTarget2 + EFSMountTarget3: + Description: The EFS MountTarget3 + Value: !Ref MountTarget3 + EFSMountTarget4: + Description: The EFS MountTarget4 + Value: !Ref MountTarget4 diff --git a/assets/queries/cloudFormation/aws/efs_not_encrypted/test/positive3.yaml b/assets/queries/cloudFormation/aws/efs_not_encrypted/test/positive3.yaml new file mode 100644 index 00000000000..67765f48f93 --- /dev/null +++ b/assets/queries/cloudFormation/aws/efs_not_encrypted/test/positive3.yaml @@ -0,0 +1,108 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "Create EFS system and Mount Targets for test VPC" +Parameters: + VPC: + Type: String + Description: The VPC identity + Default: vpc-ID + SubnetID1: + Type: String + Description: The subnet where to launch the service + Default: subnet-ID + SubnetID2: + Type: String + Description: the subnet where to Launch the service + Default: subnet-ID + SubnetID3: + Type: String + Description: The subnet where to launch the service + Default: subnet-ID + SubnetID4: + Type: String + Description: the subnet where to Launch the service + Default: subnet-ID +Resources: + EFSSecurityGroup: + Type: "AWS::EC2::SecurityGroup" + Properties: + GroupDescription: "security group for the prod EFS" + GroupName: "test-EFS-SG" + VpcId: !Ref VPC + SecurityGroupIngress: + - SourceSecurityGroupId: sg-ID + Description: "servers to connect to efs" + FromPort: 2049 + IpProtocol: "tcp" + ToPort: 2049 + Tags: + - Key: Environment + Value: prod + - Key: Name + Value: test-VPC-EFS-SG + - Key: Project + Value: ITEngineering + EFSFileSystem01: + Type: AWS::EFS::FileSystem + Properties: + BackupPolicy: + Status: ENABLED + Encrypted: "false" + LifecyclePolicies: + - TransitionToIA: AFTER_60_DAYS + PerformanceMode: generalPurpose + ThroughputMode: bursting + FileSystemTags: + - Key: Environment + Value: prod + - Key: Name + Value: test-VPC-EFS + - Key: Project + Value: ITEngineering + MountTarget1: + Type: AWS::EFS::MountTarget + Properties: + FileSystemId: !Ref EFSFileSystem01 + IpAddress: "*.*.*.*" + SecurityGroups: + - !Ref EFSSecurityGroup + SubnetId: !Ref SubnetID1 + MountTarget2: + Type: AWS::EFS::MountTarget + Properties: + FileSystemId: !Ref EFSFileSystem01 + IpAddress: "*.*.*.*" + SecurityGroups: + - !Ref EFSSecurityGroup + SubnetId: !Ref SubnetID2 + MountTarget3: + Type: AWS::EFS::MountTarget + Properties: + FileSystemId: !Ref EFSFileSystem01 + IpAddress: "*.*.*.*" + SecurityGroups: + - !Ref EFSSecurityGroup + SubnetId: !Ref SubnetID3 + MountTarget4: + Type: AWS::EFS::MountTarget + Properties: + FileSystemId: !Ref EFSFileSystem01 + IpAddress: "*.*.*.*" + SecurityGroups: + - !Ref EFSSecurityGroup + SubnetId: !Ref SubnetID4 +Outputs: + EFS: + Description: The created EFS + Value: !Ref EFSFileSystem01 + EFSMountTarget1: + Description: The EFS MountTarget1 + Value: !Ref MountTarget1 + EFSMountTarget2: + Description: The EFS MountTarget2 + Value: !Ref MountTarget2 + EFSMountTarget3: + Description: The EFS MountTarget3 + Value: !Ref MountTarget3 + EFSMountTarget4: + Description: The EFS MountTarget4 + Value: !Ref MountTarget4 diff --git a/assets/queries/cloudFormation/aws/efs_not_encrypted/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/efs_not_encrypted/test/positive_expected_result.json index 519a46991ae..fc9de30c639 100644 --- a/assets/queries/cloudFormation/aws/efs_not_encrypted/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/efs_not_encrypted/test/positive_expected_result.json @@ -10,5 +10,11 @@ "severity": "HIGH", "line": 90, "fileName": "positive2.json" + }, + { + "queryName": "EFS Not Encrypted", + "severity": "HIGH", + "line": 49, + "fileName": "positive3.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/efs_without_kms/query.rego b/assets/queries/cloudFormation/aws/efs_without_kms/query.rego index 203e02d92c5..5cf30cd277b 100644 --- a/assets/queries/cloudFormation/aws/efs_without_kms/query.rego +++ b/assets/queries/cloudFormation/aws/efs_without_kms/query.rego @@ -8,7 +8,7 @@ CxPolicy[result] { resource = document.Resources[name] resource.Type == "AWS::EFS::FileSystem" properties := resource.Properties - properties.Encrypted == false + cf_lib.isCloudFormationFalse(properties.Encrypted) not common_lib.valid_key(properties, "KmsKeyId") result := { diff --git a/assets/queries/cloudFormation/aws/efs_without_kms/test/negative3.yaml b/assets/queries/cloudFormation/aws/efs_without_kms/test/negative3.yaml new file mode 100644 index 00000000000..81acdf324cf --- /dev/null +++ b/assets/queries/cloudFormation/aws/efs_without_kms/test/negative3.yaml @@ -0,0 +1,147 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "Create EFS system and Mount Targets for test VPC" +Parameters: + VPC: + Type: String + Description: The VPC identity + Default: vpc-ID + SubnetID1: + Type: String + Description: The subnet where to launch the service + Default: subnet-ID + SubnetID2: + Type: String + Description: the subnet where to Launch the service + Default: subnet-ID + SubnetID3: + Type: String + Description: The subnet where to launch the service + Default: subnet-ID + SubnetID4: + Type: String + Description: the subnet where to Launch the service + Default: subnet-ID +Resources: + EFSKMSKey: + Type: AWS::KMS::Key + Properties: + Description: "An example CMK with KMS" + KeyPolicy: + Version: "2012-10-17" + Id: "efs-default-key1" + Statement: + - Sid: "Allow administration of the key" + Effect: "Allow" + Principal: + AWS: "arn:aws:iam::999999999999:user/roger" + Action: + - "kms:Create*" + - "kms:Describe*" + - "kms:Enable*" + - "kms:List*" + - "kms:Put*" + - "kms:Update*" + - "kms:Revoke*" + - "kms:Disable*" + - "kms:Get*" + - "kms:Delete*" + - "kms:ScheduleKeyDeletion" + - "kms:CancelKeyDeletion" + Resource: "*" + - Sid: "Allow use of the key" + Effect: "Allow" + Principal: + AWS: "arn:aws:iam::999999999999:user/roger" + Action: + - "kms:DescribeKey" + - "kms:Encrypt" + - "kms:Decrypt" + - "kms:ReEncrypt*" + - "kms:GenerateDataKey" + - "kms:GenerateDataKeyWithoutPlaintext" + Resource: "*" + EFSSecurityGroup: + Type: "AWS::EC2::SecurityGroup" + Properties: + GroupDescription: "security group for the prod EFS" + GroupName: "test-EFS-SG" + VpcId: !Ref VPC + SecurityGroupIngress: + - SourceSecurityGroupId: sg-ID + Description: "servers to connect to efs" + FromPort: 2049 + IpProtocol: "tcp" + ToPort: 2049 + Tags: + - Key: Environment + Value: prod + - Key: Name + Value: test-VPC-EFS-SG + - Key: Project + Value: ITEngineering + EFSFileSystem01: + Type: AWS::EFS::FileSystem + Properties: + BackupPolicy: + Status: ENABLED + Encrypted: "false" + KmsKeyId: !Ref EFSKMSKey + LifecyclePolicies: + - TransitionToIA: AFTER_60_DAYS + PerformanceMode: generalPurpose + ThroughputMode: bursting + FileSystemTags: + - Key: Environment + Value: prod + - Key: Name + Value: test-VPC-EFS + - Key: Project + Value: ITEngineering + MountTarget1: + Type: AWS::EFS::MountTarget + Properties: + FileSystemId: !Ref EFSFileSystem01 + IpAddress: "*.*.*.*" + SecurityGroups: + - !Ref EFSSecurityGroup + SubnetId: !Ref SubnetID1 + MountTarget2: + Type: AWS::EFS::MountTarget + Properties: + FileSystemId: !Ref EFSFileSystem01 + IpAddress: "*.*.*.*" + SecurityGroups: + - !Ref EFSSecurityGroup + SubnetId: !Ref SubnetID2 + MountTarget3: + Type: AWS::EFS::MountTarget + Properties: + FileSystemId: !Ref EFSFileSystem01 + IpAddress: "*.*.*.*" + SecurityGroups: + - !Ref EFSSecurityGroup + SubnetId: !Ref SubnetID3 + MountTarget4: + Type: AWS::EFS::MountTarget + Properties: + FileSystemId: !Ref EFSFileSystem01 + IpAddress: "*.*.*.*" + SecurityGroups: + - !Ref EFSSecurityGroup + SubnetId: !Ref SubnetID4 +Outputs: + EFS: + Description: The created EFS + Value: !Ref EFSFileSystem01 + EFSMountTarget1: + Description: The EFS MountTarget1 + Value: !Ref MountTarget1 + EFSMountTarget2: + Description: The EFS MountTarget2 + Value: !Ref MountTarget2 + EFSMountTarget3: + Description: The EFS MountTarget3 + Value: !Ref MountTarget3 + EFSMountTarget4: + Description: The EFS MountTarget4 + Value: !Ref MountTarget4 diff --git a/assets/queries/cloudFormation/aws/efs_without_kms/test/positive3.yaml b/assets/queries/cloudFormation/aws/efs_without_kms/test/positive3.yaml new file mode 100644 index 00000000000..29acbd3c7b6 --- /dev/null +++ b/assets/queries/cloudFormation/aws/efs_without_kms/test/positive3.yaml @@ -0,0 +1,146 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "Create EFS system and Mount Targets for test VPC" +Parameters: + VPC: + Type: String + Description: The VPC identity + Default: vpc-ID + SubnetID1: + Type: String + Description: The subnet where to launch the service + Default: subnet-ID + SubnetID2: + Type: String + Description: the subnet where to Launch the service + Default: subnet-ID + SubnetID3: + Type: String + Description: The subnet where to launch the service + Default: subnet-ID + SubnetID4: + Type: String + Description: the subnet where to Launch the service + Default: subnet-ID +Resources: + EFSKMSKey: + Type: AWS::KMS::Key + Properties: + Description: "An example CMK with KMS" + KeyPolicy: + Version: "2012-10-17" + Id: "efs-default-key1" + Statement: + - Sid: "Allow administration of the key" + Effect: "Allow" + Principal: + AWS: "arn:aws:iam::999999999999:user/roger" + Action: + - "kms:Create*" + - "kms:Describe*" + - "kms:Enable*" + - "kms:List*" + - "kms:Put*" + - "kms:Update*" + - "kms:Revoke*" + - "kms:Disable*" + - "kms:Get*" + - "kms:Delete*" + - "kms:ScheduleKeyDeletion" + - "kms:CancelKeyDeletion" + Resource: "*" + - Sid: "Allow use of the key" + Effect: "Allow" + Principal: + AWS: "arn:aws:iam::999999999999:user/roger" + Action: + - "kms:DescribeKey" + - "kms:Encrypt" + - "kms:Decrypt" + - "kms:ReEncrypt*" + - "kms:GenerateDataKey" + - "kms:GenerateDataKeyWithoutPlaintext" + Resource: "*" + EFSSecurityGroup: + Type: "AWS::EC2::SecurityGroup" + Properties: + GroupDescription: "security group for the prod EFS" + GroupName: "test-EFS-SG" + VpcId: !Ref VPC + SecurityGroupIngress: + - SourceSecurityGroupId: sg-ID + Description: "servers to connect to efs" + FromPort: 2049 + IpProtocol: "tcp" + ToPort: 2049 + Tags: + - Key: Environment + Value: prod + - Key: Name + Value: test-VPC-EFS-SG + - Key: Project + Value: ITEngineering + EFSFileSystem01: + Type: AWS::EFS::FileSystem + Properties: + BackupPolicy: + Status: ENABLED + Encrypted: "false" + LifecyclePolicies: + - TransitionToIA: AFTER_60_DAYS + PerformanceMode: generalPurpose + ThroughputMode: bursting + FileSystemTags: + - Key: Environment + Value: prod + - Key: Name + Value: test-VPC-EFS + - Key: Project + Value: ITEngineering + MountTarget1: + Type: AWS::EFS::MountTarget + Properties: + FileSystemId: !Ref EFSFileSystem01 + IpAddress: "*.*.*.*" + SecurityGroups: + - !Ref EFSSecurityGroup + SubnetId: !Ref SubnetID1 + MountTarget2: + Type: AWS::EFS::MountTarget + Properties: + FileSystemId: !Ref EFSFileSystem01 + IpAddress: "*.*.*.*" + SecurityGroups: + - !Ref EFSSecurityGroup + SubnetId: !Ref SubnetID2 + MountTarget3: + Type: AWS::EFS::MountTarget + Properties: + FileSystemId: !Ref EFSFileSystem01 + IpAddress: "*.*.*.*" + SecurityGroups: + - !Ref EFSSecurityGroup + SubnetId: !Ref SubnetID3 + MountTarget4: + Type: AWS::EFS::MountTarget + Properties: + FileSystemId: !Ref EFSFileSystem01 + IpAddress: "*.*.*.*" + SecurityGroups: + - !Ref EFSSecurityGroup + SubnetId: !Ref SubnetID4 +Outputs: + EFS: + Description: The created EFS + Value: !Ref EFSFileSystem01 + EFSMountTarget1: + Description: The EFS MountTarget1 + Value: !Ref MountTarget1 + EFSMountTarget2: + Description: The EFS MountTarget2 + Value: !Ref MountTarget2 + EFSMountTarget3: + Description: The EFS MountTarget3 + Value: !Ref MountTarget3 + EFSMountTarget4: + Description: The EFS MountTarget4 + Value: !Ref MountTarget4 diff --git a/assets/queries/cloudFormation/aws/efs_without_kms/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/efs_without_kms/test/positive_expected_result.json index 7e00866f933..b3569a8fb15 100644 --- a/assets/queries/cloudFormation/aws/efs_without_kms/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/efs_without_kms/test/positive_expected_result.json @@ -10,5 +10,11 @@ "severity": "LOW", "line": 157, "fileName": "positive2.json" + }, + { + "queryName": "EFS Without KMS", + "severity": "LOW", + "line": 82, + "fileName": "positive3.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/elasticache_with_disabled_at_rest_encryption/query.rego b/assets/queries/cloudFormation/aws/elasticache_with_disabled_at_rest_encryption/query.rego index 164de002721..0a9da457e56 100644 --- a/assets/queries/cloudFormation/aws/elasticache_with_disabled_at_rest_encryption/query.rego +++ b/assets/queries/cloudFormation/aws/elasticache_with_disabled_at_rest_encryption/query.rego @@ -9,7 +9,7 @@ CxPolicy[result] { resource.Type = "AWS::ElastiCache::ReplicationGroup" properties := resource.Properties lower(properties.Engine) == "redis" - properties.AtRestEncryptionEnabled == false + cf_lib.isCloudFormationFalse(properties.AtRestEncryptionEnabled) result := { "documentId": input.document[i].id, "resourceType": resource.Type, diff --git a/assets/queries/cloudFormation/aws/elasticache_with_disabled_at_rest_encryption/test/negative3.yaml b/assets/queries/cloudFormation/aws/elasticache_with_disabled_at_rest_encryption/test/negative3.yaml new file mode 100644 index 00000000000..48ad0edfa60 --- /dev/null +++ b/assets/queries/cloudFormation/aws/elasticache_with_disabled_at_rest_encryption/test/negative3.yaml @@ -0,0 +1,30 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: 'State: ElastiCache redis, a cloudonaut.io template' +Resources: + ReplicationGroup: + DeletionPolicy: Snapshot + UpdateReplacePolicy: Snapshot + Type: AWS::ElastiCache::ReplicationGroup + Properties: + ReplicationGroupDescription: !Ref 'AWS::StackName' + AtRestEncryptionEnabled: "true" + AuthToken: !If [HasAuthToken, !Ref AuthToken, !Ref 'AWS::NoValue'] + AutomaticFailoverEnabled: !If [HasAutomaticFailoverEnabled, "true", "false"] + CacheNodeType: !Ref CacheNodeType + CacheParameterGroupName: !Ref CacheParameterGroup + CacheSubnetGroupName: !Ref CacheSubnetGroupName + Engine: redis + EngineVersion: !Ref EngineVersion + KmsKeyId: !If [HasKmsKey, {'Fn::ImportValue': !Sub '${ParentKmsKeyStack}-KeyId'}, !Ref 'AWS::NoValue'] + NotificationTopicArn: !If [HasAlertTopic, {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'}, !Ref 'AWS::NoValue'] + NumNodeGroups: !Ref NumShards + ReplicasPerNodeGroup: !Ref NumReplicas + PreferredMaintenanceWindow: 'sat:07:00-sat:08:00' + SecurityGroupIds: + - !Ref SecurityGroup + SnapshotName: !If [HasSnapshotName, !Ref SnapshotName, !Ref 'AWS::NoValue'] + SnapshotRetentionLimit: !Ref SnapshotRetentionLimit + SnapshotWindow: '00:00-03:00' + TransitEncryptionEnabled: !Ref TransitEncryption + UpdatePolicy: + UseOnlineResharding: "true" diff --git a/assets/queries/cloudFormation/aws/elasticache_with_disabled_at_rest_encryption/test/positive5.yaml b/assets/queries/cloudFormation/aws/elasticache_with_disabled_at_rest_encryption/test/positive5.yaml new file mode 100644 index 00000000000..89866141264 --- /dev/null +++ b/assets/queries/cloudFormation/aws/elasticache_with_disabled_at_rest_encryption/test/positive5.yaml @@ -0,0 +1,28 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: 'State: ElastiCache redis, a cloudonaut.io template' +Resources: + ReplicationGroup: + DeletionPolicy: Snapshot + UpdateReplacePolicy: Snapshot + Type: AWS::ElastiCache::ReplicationGroup + Properties: + ReplicationGroupDescription: !Ref 'AWS::StackName' + AtRestEncryptionEnabled: "false" + AuthToken: !If [HasAuthToken, !Ref AuthToken, !Ref 'AWS::NoValue'] + AutomaticFailoverEnabled: !If [HasAutomaticFailoverEnabled, "true", "false"] + CacheNodeType: !Ref CacheNodeType + CacheParameterGroupName: !Ref CacheParameterGroup + CacheSubnetGroupName: !Ref CacheSubnetGroupName + Engine: redis + EngineVersion: !Ref EngineVersion + KmsKeyId: !If [HasKmsKey, {'Fn::ImportValue': !Sub '${ParentKmsKeyStack}-KeyId'}, !Ref 'AWS::NoValue'] + NotificationTopicArn: !If [HasAlertTopic, {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'}, !Ref 'AWS::NoValue'] + NumNodeGroups: !Ref NumShards + ReplicasPerNodeGroup: !Ref NumReplicas + PreferredMaintenanceWindow: 'sat:07:00-sat:08:00' + SecurityGroupIds: + - !Ref SecurityGroup + SnapshotName: !If [HasSnapshotName, !Ref SnapshotName, !Ref 'AWS::NoValue'] + SnapshotRetentionLimit: !Ref SnapshotRetentionLimit + SnapshotWindow: '00:00-03:00' + TransitEncryptionEnabled: !Ref TransitEncryption diff --git a/assets/queries/cloudFormation/aws/elasticache_with_disabled_at_rest_encryption/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/elasticache_with_disabled_at_rest_encryption/test/positive_expected_result.json index 263c0466ae7..36188c1bb62 100644 --- a/assets/queries/cloudFormation/aws/elasticache_with_disabled_at_rest_encryption/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/elasticache_with_disabled_at_rest_encryption/test/positive_expected_result.json @@ -1,15 +1,15 @@ [ { - "line": 10, - "fileName": "positive1.yaml", "queryName": "ElastiCache With Disabled at Rest Encryption", - "severity": "HIGH" + "severity": "HIGH", + "line": 10, + "fileName": "positive1.yaml" }, { + "queryName": "ElastiCache With Disabled at Rest Encryption", "severity": "HIGH", "line": 8, - "fileName": "positive2.yaml", - "queryName": "ElastiCache With Disabled at Rest Encryption" + "fileName": "positive2.yaml" }, { "queryName": "ElastiCache With Disabled at Rest Encryption", @@ -22,5 +22,11 @@ "severity": "HIGH", "line": 7, "fileName": "positive4.json" + }, + { + "queryName": "ElastiCache With Disabled at Rest Encryption", + "severity": "HIGH", + "line": 10, + "fileName": "positive5.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/elasticache_with_disabled_transit_encryption/query.rego b/assets/queries/cloudFormation/aws/elasticache_with_disabled_transit_encryption/query.rego index 7045636a762..0edb62f64cc 100644 --- a/assets/queries/cloudFormation/aws/elasticache_with_disabled_transit_encryption/query.rego +++ b/assets/queries/cloudFormation/aws/elasticache_with_disabled_transit_encryption/query.rego @@ -9,7 +9,7 @@ CxPolicy[result] { resource.Type = "AWS::ElastiCache::ReplicationGroup" properties := resource.Properties lower(properties.Engine) == "redis" - properties.TransitEncryptionEnabled == false + cf_lib.isCloudFormationFalse(properties.TransitEncryptionEnabled) result := { "documentId": input.document[i].id, "resourceType": resource.Type, diff --git a/assets/queries/cloudFormation/aws/elasticache_with_disabled_transit_encryption/test/negative3.yaml b/assets/queries/cloudFormation/aws/elasticache_with_disabled_transit_encryption/test/negative3.yaml new file mode 100644 index 00000000000..f98b08d0843 --- /dev/null +++ b/assets/queries/cloudFormation/aws/elasticache_with_disabled_transit_encryption/test/negative3.yaml @@ -0,0 +1,29 @@ +Resources: + ReplicationGroup: + DeletionPolicy: Snapshot + UpdateReplacePolicy: Snapshot + Type: AWS::ElastiCache::ReplicationGroup + Properties: + ReplicationGroupDescription: !Ref 'AWS::StackName' + AtRestEncryptionEnabled: "true" + AuthToken: !If [HasAuthToken, !Ref AuthToken, !Ref 'AWS::NoValue'] + AutomaticFailoverEnabled: !If [HasAutomaticFailoverEnabled, "true", "false"] + CacheNodeType: !Ref CacheNodeType + CacheParameterGroupName: !Ref CacheParameterGroup + CacheSubnetGroupName: !Ref CacheSubnetGroupName + Engine: redis + EngineVersion: !Ref EngineVersion + KmsKeyId: !If [HasKmsKey, {'Fn::ImportValue': !Sub '${ParentKmsKeyStack}-KeyId'}, !Ref 'AWS::NoValue'] + NotificationTopicArn: !If [HasAlertTopic, {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'}, !Ref 'AWS::NoValue'] + NumNodeGroups: !Ref NumShards + ReplicasPerNodeGroup: !Ref NumReplicas + PreferredMaintenanceWindow: 'sat:07:00-sat:08:00' + SecurityGroupIds: + - !Ref SecurityGroup + SnapshotName: !If [HasSnapshotName, !Ref SnapshotName, !Ref 'AWS::NoValue'] + SnapshotRetentionLimit: !Ref SnapshotRetentionLimit + SnapshotWindow: '00:00-03:00' + TransitEncryptionEnabled: "true" + UpdatePolicy: + UseOnlineResharding: "true" + diff --git a/assets/queries/cloudFormation/aws/elasticache_with_disabled_transit_encryption/test/positive5.yaml b/assets/queries/cloudFormation/aws/elasticache_with_disabled_transit_encryption/test/positive5.yaml new file mode 100644 index 00000000000..b112088fb45 --- /dev/null +++ b/assets/queries/cloudFormation/aws/elasticache_with_disabled_transit_encryption/test/positive5.yaml @@ -0,0 +1,27 @@ +Resources: + ReplicationGroup: + DeletionPolicy: Snapshot + UpdateReplacePolicy: Snapshot + Type: AWS::ElastiCache::ReplicationGroup + Properties: + ReplicationGroupDescription: !Ref 'AWS::StackName' + AtRestEncryptionEnabled: "true" + AuthToken: !If [HasAuthToken, !Ref AuthToken, !Ref 'AWS::NoValue'] + AutomaticFailoverEnabled: !If [HasAutomaticFailoverEnabled, "true", "false"] + CacheNodeType: !Ref CacheNodeType + CacheParameterGroupName: !Ref CacheParameterGroup + CacheSubnetGroupName: !Ref CacheSubnetGroupName + Engine: redis + EngineVersion: !Ref EngineVersion + KmsKeyId: !If [HasKmsKey, {'Fn::ImportValue': !Sub '${ParentKmsKeyStack}-KeyId'}, !Ref 'AWS::NoValue'] + NotificationTopicArn: !If [HasAlertTopic, {'Fn::ImportValue': !Sub '${ParentAlertStack}-TopicARN'}, !Ref 'AWS::NoValue'] + NumNodeGroups: !Ref NumShards + ReplicasPerNodeGroup: !Ref NumReplicas + PreferredMaintenanceWindow: 'sat:07:00-sat:08:00' + SecurityGroupIds: + - !Ref SecurityGroup + SnapshotName: !If [HasSnapshotName, !Ref SnapshotName, !Ref 'AWS::NoValue'] + SnapshotRetentionLimit: !Ref SnapshotRetentionLimit + SnapshotWindow: '00:00-03:00' + UpdatePolicy: + UseOnlineResharding: "true" diff --git a/assets/queries/cloudFormation/aws/elasticache_with_disabled_transit_encryption/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/elasticache_with_disabled_transit_encryption/test/positive_expected_result.json index 596b60304b4..303cc495823 100644 --- a/assets/queries/cloudFormation/aws/elasticache_with_disabled_transit_encryption/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/elasticache_with_disabled_transit_encryption/test/positive_expected_result.json @@ -1,26 +1,32 @@ [ { - "fileName": "positive2.yaml", "queryName": "ElastiCache With Disabled Transit Encryption", "severity": "MEDIUM", - "line": 26 + "line": 6, + "fileName": "positive1.yaml" }, { + "queryName": "ElastiCache With Disabled Transit Encryption", "severity": "MEDIUM", - "line": 6, - "fileName": "positive1.yaml", - "queryName": "ElastiCache With Disabled Transit Encryption" + "line": 26, + "fileName": "positive2.yaml" }, { - "line": 4, - "fileName": "positive3.json", "queryName": "ElastiCache With Disabled Transit Encryption", - "severity": "MEDIUM" + "severity": "MEDIUM", + "line": 4, + "fileName": "positive3.json" }, { "queryName": "ElastiCache With Disabled Transit Encryption", "severity": "MEDIUM", "line": 18, "fileName": "positive4.json" + }, + { + "queryName": "ElastiCache With Disabled Transit Encryption", + "severity": "MEDIUM", + "line": 6, + "fileName": "positive5.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/elasticsearch_logs_disabled/query.rego b/assets/queries/cloudFormation/aws/elasticsearch_logs_disabled/query.rego index ab0a8ed3b9b..0fe4da97c98 100644 --- a/assets/queries/cloudFormation/aws/elasticsearch_logs_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/elasticsearch_logs_disabled/query.rego @@ -12,7 +12,7 @@ CxPolicy[result] { resource.Type == "AWS::Elasticsearch::Domain" logs := resource.Properties.LogPublishingOptions[logName] logName == LogTypes[j] - logs.Enabled == "false" + cf_lib.isCloudFormationFalse(logs.Enabled) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/elasticsearch_logs_disabled/test/positive6.yaml b/assets/queries/cloudFormation/aws/elasticsearch_logs_disabled/test/positive6.yaml new file mode 100644 index 00000000000..407b1d2bdda --- /dev/null +++ b/assets/queries/cloudFormation/aws/elasticsearch_logs_disabled/test/positive6.yaml @@ -0,0 +1,48 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: ElasticsearchDomain resource +Resources: + ElasticsearchDomain: + Type: "AWS::Elasticsearch::Domain" + Properties: + DomainName: + Ref: DomainName + ElasticsearchVersion: + Ref: ElasticsearchVersion + ElasticsearchClusterConfig: + InstanceCount: "1" + InstanceType: + Ref: InstanceType + EBSOptions: + EBSEnabled: true + Iops: 0 + VolumeSize: 10 + VolumeType: standard + SnapshotOptions: + AutomatedSnapshotStartHour: "0" + AccessPolicies: + Version: "2012-10-17" + Statement: + - Effect: Deny + Principal: + AWS: "*" + Action: "es:*" + Resource: "*" + LogPublishingOptions: + SEARCH_SLOW_LOGS: + CloudWatchLogsLogGroupArn: >- + arn:aws:logs:us-east-1:123456789012:log-group:/aws/aes/domains/es-slow-logs + Enabled: false + INDEX_SLOW_LOGS: + CloudWatchLogsLogGroupArn: >- + arn:aws:logs:us-east-1:123456789012:log-group:/aws/aes/domains/es-index-slow-logs + Enabled: true + ES_APPLICATION_LOGS: + CloudWatchLogsLogGroupArn: >- + arn:aws:logs:us-east-1:123456789012:log-group:/aws/aes/domains/es-application-logs + Enabled: true + AUDIT_LOGS: + CloudWatchLogsLogGroupArn: >- + arn:aws:logs:us-east-1:123456789012:log-group:/aws/aes/domains/es-audit-logs + Enabled: true + AdvancedOptions: + rest.action.multi.allow_explicit_index: true diff --git a/assets/queries/cloudFormation/aws/elasticsearch_logs_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/elasticsearch_logs_disabled/test/positive_expected_result.json index c09c02584da..3baef2425e9 100644 --- a/assets/queries/cloudFormation/aws/elasticsearch_logs_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/elasticsearch_logs_disabled/test/positive_expected_result.json @@ -28,5 +28,11 @@ "severity": "MEDIUM", "line": 43, "fileName": "positive5.json" + }, + { + "queryName": "Elasticsearch Logs Disabled", + "severity": "MEDIUM", + "line": 34, + "fileName": "positive6.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/elasticsearch_not_encrypted_at_rest/query.rego b/assets/queries/cloudFormation/aws/elasticsearch_not_encrypted_at_rest/query.rego index eec58a1cdcb..be505170084 100644 --- a/assets/queries/cloudFormation/aws/elasticsearch_not_encrypted_at_rest/query.rego +++ b/assets/queries/cloudFormation/aws/elasticsearch_not_encrypted_at_rest/query.rego @@ -30,7 +30,7 @@ CxPolicy[result] { resource.Type == "AWS::Elasticsearch::Domain" properties := resource.Properties - properties.EncryptionAtRestOptions.Enabled != true + not cf_lib.isCloudFormationTrue(properties.EncryptionAtRestOptions.Enabled) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/elasticsearch_not_encrypted_at_rest/test/negative1.yaml b/assets/queries/cloudFormation/aws/elasticsearch_not_encrypted_at_rest/test/negative1.yaml index 41c885d85bb..2e320554e2d 100644 --- a/assets/queries/cloudFormation/aws/elasticsearch_not_encrypted_at_rest/test/negative1.yaml +++ b/assets/queries/cloudFormation/aws/elasticsearch_not_encrypted_at_rest/test/negative1.yaml @@ -13,9 +13,9 @@ Resources: DedicatedMasterType: "m3.medium.elasticsearch" DedicatedMasterCount: "3" EncryptionAtRestOptions: - Enabled: true + Enabled: "true" EBSOptions: - EBSEnabled: true + EBSEnabled: "true" Iops: 0 VolumeSize: 20 VolumeType: "gp2" diff --git a/assets/queries/cloudFormation/aws/elasticsearch_not_encrypted_at_rest/test/negative3.yaml b/assets/queries/cloudFormation/aws/elasticsearch_not_encrypted_at_rest/test/negative3.yaml new file mode 100644 index 00000000000..41c885d85bb --- /dev/null +++ b/assets/queries/cloudFormation/aws/elasticsearch_not_encrypted_at_rest/test/negative3.yaml @@ -0,0 +1,34 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: Creates RDS Cluster +Resources: + ElasticsearchDomain: + Type: AWS::Elasticsearch::Domain + Properties: + DomainName: "test" + ElasticsearchClusterConfig: + DedicatedMasterEnabled: "true" + InstanceCount: "2" + ZoneAwarenessEnabled: "true" + InstanceType: "m3.medium.elasticsearch" + DedicatedMasterType: "m3.medium.elasticsearch" + DedicatedMasterCount: "3" + EncryptionAtRestOptions: + Enabled: true + EBSOptions: + EBSEnabled: true + Iops: 0 + VolumeSize: 20 + VolumeType: "gp2" + SnapshotOptions: + AutomatedSnapshotStartHour: "0" + AccessPolicies: + Version: "2012-10-17" + Statement: + - + Effect: "Allow" + Principal: + AWS: "arn:aws:iam::123456789012:user/es-user" + Action: "es:*" + Resource: "arn:aws:es:us-east-1:846973539254:domain/test/*" + AdvancedOptions: + rest.action.multi.allow_explicit_index: "true" diff --git a/assets/queries/cloudFormation/aws/elasticsearch_not_encrypted_at_rest/test/positive5.yaml b/assets/queries/cloudFormation/aws/elasticsearch_not_encrypted_at_rest/test/positive5.yaml new file mode 100644 index 00000000000..37fa8a5b303 --- /dev/null +++ b/assets/queries/cloudFormation/aws/elasticsearch_not_encrypted_at_rest/test/positive5.yaml @@ -0,0 +1,35 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: Creates RDS Cluster +Resources: + ElasticsearchDomain: + Type: AWS::Elasticsearch::Domain + Properties: + DomainName: "test" + ElasticsearchClusterConfig: + DedicatedMasterEnabled: "true" + InstanceCount: "2" + ZoneAwarenessEnabled: "true" + InstanceType: "m3.medium.elasticsearch" + DedicatedMasterType: "m3.medium.elasticsearch" + DedicatedMasterCount: "3" + EncryptionAtRestOptions: + Enabled: "false" + EBSOptions: + EBSEnabled: "true" + Iops: 0 + VolumeSize: 20 + VolumeType: "gp2" + SnapshotOptions: + AutomatedSnapshotStartHour: "0" + AccessPolicies: + Version: "2012-10-17" + Statement: + - + Effect: "Allow" + Principal: + AWS: "arn:aws:iam::123456789012:user/es-user" + Action: "es:*" + Resource: "arn:aws:es:us-east-1:846973539254:domain/test/*" + AdvancedOptions: + rest.action.multi.allow_explicit_index: "true" + diff --git a/assets/queries/cloudFormation/aws/elasticsearch_not_encrypted_at_rest/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/elasticsearch_not_encrypted_at_rest/test/positive_expected_result.json index e8b566a38f5..572646d6388 100644 --- a/assets/queries/cloudFormation/aws/elasticsearch_not_encrypted_at_rest/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/elasticsearch_not_encrypted_at_rest/test/positive_expected_result.json @@ -2,25 +2,31 @@ { "queryName": "ElasticSearch Not Encrypted At Rest", "severity": "HIGH", - "line": 6, - "fileName": "positive2.yaml" + "line": 16, + "fileName": "positive1.yaml" }, { "queryName": "ElasticSearch Not Encrypted At Rest", "severity": "HIGH", - "line": 16, - "fileName": "positive1.yaml" + "line": 6, + "fileName": "positive2.yaml" }, { - "line": 8, - "fileName": "positive3.json", "queryName": "ElasticSearch Not Encrypted At Rest", - "severity": "HIGH" + "severity": "HIGH", + "line": 8, + "fileName": "positive3.json" }, { "queryName": "ElasticSearch Not Encrypted At Rest", "severity": "HIGH", "line": 5, "fileName": "positive4.json" + }, + { + "queryName": "ElasticSearch Not Encrypted At Rest", + "severity": "HIGH", + "line": 16, + "fileName": "positive5.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/elasticsearch_with_https_disabled/query.rego b/assets/queries/cloudFormation/aws/elasticsearch_with_https_disabled/query.rego index f4781efe848..669b1171e06 100644 --- a/assets/queries/cloudFormation/aws/elasticsearch_with_https_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/elasticsearch_with_https_disabled/query.rego @@ -54,7 +54,7 @@ CxPolicy[result] { field := types[type] resource.Type == field - resource.Properties.DomainEndpointOptions.EnforceHTTPS == false + cf_lib.isCloudFormationFalse(resource.Properties.DomainEndpointOptions.EnforceHTTPS) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/elasticsearch_with_https_disabled/test/negative2.yaml b/assets/queries/cloudFormation/aws/elasticsearch_with_https_disabled/test/negative2.yaml new file mode 100644 index 00000000000..3d1e33df4bc --- /dev/null +++ b/assets/queries/cloudFormation/aws/elasticsearch_with_https_disabled/test/negative2.yaml @@ -0,0 +1,16 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: description +Resources: + OpenSearchDomain: + Type: AWS::OpenSearchService::Domain + Properties: + DomainName: my-opensearch-domain + ElasticsearchVersion: "7.9" + ElasticsearchClusterConfig: + InstanceType: m5.large.search + InstanceCount: 1 + AdvancedOptions: + rest.action.multi.allow_explicit_index: "true" + DomainEndpointOptions: + EnforceHTTPS: "true" + TLSSecurityPolicy: "Policy-Min-TLS-1-2-2019-07" diff --git a/assets/queries/cloudFormation/aws/elasticsearch_with_https_disabled/test/positive4.yaml b/assets/queries/cloudFormation/aws/elasticsearch_with_https_disabled/test/positive4.yaml new file mode 100644 index 00000000000..97755ca32c7 --- /dev/null +++ b/assets/queries/cloudFormation/aws/elasticsearch_with_https_disabled/test/positive4.yaml @@ -0,0 +1,16 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: description +Resources: + OpenSearchDomain: + Type: AWS::OpenSearchService::Domain + Properties: + DomainName: my-opensearch-domain + ElasticsearchVersion: "7.9" + ElasticsearchClusterConfig: + InstanceType: m5.large.search + InstanceCount: 1 + AdvancedOptions: + rest.action.multi.allow_explicit_index: "true" + DomainEndpointOptions: + EnforceHTTPS: "false" + TLSSecurityPolicy: "Policy-Min-TLS-1-2-2019-07" diff --git a/assets/queries/cloudFormation/aws/elasticsearch_with_https_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/elasticsearch_with_https_disabled/test/positive_expected_result.json index 957c16e928b..2e61a6091c4 100644 --- a/assets/queries/cloudFormation/aws/elasticsearch_with_https_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/elasticsearch_with_https_disabled/test/positive_expected_result.json @@ -16,5 +16,11 @@ "severity": "MEDIUM", "line": 6, "fileName": "positive3.yaml" + }, + { + "queryName": "Elasticsearch with HTTPS disabled", + "severity": "MEDIUM", + "line": 15, + "fileName": "positive4.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/elasticsearch_without_slow_logs/query.rego b/assets/queries/cloudFormation/aws/elasticsearch_without_slow_logs/query.rego index 921311abc69..be7bfc17153 100644 --- a/assets/queries/cloudFormation/aws/elasticsearch_without_slow_logs/query.rego +++ b/assets/queries/cloudFormation/aws/elasticsearch_without_slow_logs/query.rego @@ -33,7 +33,7 @@ CxPolicy[result] { resource.Type == "AWS::Elasticsearch::Domain" logs := resource.Properties.LogPublishingOptions[logName] logName == slowLogs[j] - logs.Enabled == "false" + cf_lib.isCloudFormationFalse(logs.Enabled) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/elasticsearch_without_slow_logs/test/positive7.yaml b/assets/queries/cloudFormation/aws/elasticsearch_without_slow_logs/test/positive7.yaml new file mode 100644 index 00000000000..c02fe62e7ab --- /dev/null +++ b/assets/queries/cloudFormation/aws/elasticsearch_without_slow_logs/test/positive7.yaml @@ -0,0 +1,40 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: ElasticsearchDomain resource +Resources: + ElasticsearchDomain: + Type: "AWS::Elasticsearch::Domain" + Properties: + DomainName: + Ref: DomainName + ElasticsearchVersion: + Ref: ElasticsearchVersion + ElasticsearchClusterConfig: + InstanceCount: "1" + InstanceType: + Ref: InstanceType + EBSOptions: + EBSEnabled: true + Iops: 0 + VolumeSize: 10 + VolumeType: standard + SnapshotOptions: + AutomatedSnapshotStartHour: "0" + AccessPolicies: + Version: "2012-10-17" + Statement: + - Effect: Deny + Principal: + AWS: "*" + Action: "es:*" + Resource: "*" + LogPublishingOptions: + SEARCH_SLOW_LOGS: + CloudWatchLogsLogGroupArn: >- + arn:aws:logs:us-east-1:123456789012:log-group:/aws/aes/domains/es-slow-logs + Enabled: false + INDEX_SLOW_LOGS: + CloudWatchLogsLogGroupArn: >- + arn:aws:logs:us-east-1:123456789012:log-group:/aws/aes/domains/es-index-slow-logs + Enabled: true + AdvancedOptions: + rest.action.multi.allow_explicit_index: true diff --git a/assets/queries/cloudFormation/aws/elasticsearch_without_slow_logs/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/elasticsearch_without_slow_logs/test/positive_expected_result.json index bf83521a0fb..b7565e542ac 100644 --- a/assets/queries/cloudFormation/aws/elasticsearch_without_slow_logs/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/elasticsearch_without_slow_logs/test/positive_expected_result.json @@ -34,5 +34,11 @@ "severity": "LOW", "line": 7, "fileName": "positive6.json" + }, + { + "queryName": "ElasticSearch Without Slow Logs", + "severity": "LOW", + "line": 34, + "fileName": "positive7.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/elb_access_log_disabled/query.rego b/assets/queries/cloudFormation/aws/elb_access_log_disabled/query.rego index 2660437553d..42310e2269f 100644 --- a/assets/queries/cloudFormation/aws/elb_access_log_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/elb_access_log_disabled/query.rego @@ -42,5 +42,5 @@ checkALP(prop) { } checkALPAttr(prop) { - prop.AccessLoggingPolicy.Enabled == false + cf_lib.isCloudFormationFalse(prop.AccessLoggingPolicy.Enabled) } diff --git a/assets/queries/cloudFormation/aws/elb_access_log_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/elb_access_log_disabled/test/negative3.yaml new file mode 100644 index 00000000000..663643ab926 --- /dev/null +++ b/assets/queries/cloudFormation/aws/elb_access_log_disabled/test/negative3.yaml @@ -0,0 +1,32 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: A simple EC2 instance +Resources: + MyLoadBalancer: + Type: AWS::ElasticLoadBalancing::LoadBalancer + Properties: + AvailabilityZones: + - "us-east-2a" + CrossZone: "true" + Listeners: + - InstancePort: "80" + InstanceProtocol: HTTP + LoadBalancerPort: "443" + Protocol: HTTPS + PolicyNames: + - My-SSLNegotiation-Policy + SSLCertificateId: arn:aws:iam::123456789012:server-certificate/my-server-certificate + HealthCheck: + Target: HTTP:80/ + HealthyThreshold: "2" + UnhealthyThreshold: "3" + Interval: "10" + Timeout: "5" + Policies: + - PolicyName: My-SSLNegotiation-Policy + PolicyType: SSLNegotiationPolicyType + Attributes: + - Name: Reference-Security-Policy + Value: ELBSecurityPolicy-TLS-1-2-2017-01 + AccessLoggingPolicy: + - Enabled: "true" + S3BucketName: teste diff --git a/assets/queries/cloudFormation/aws/elb_access_log_disabled/test/positive5.yaml b/assets/queries/cloudFormation/aws/elb_access_log_disabled/test/positive5.yaml new file mode 100644 index 00000000000..6a2b5af8a7b --- /dev/null +++ b/assets/queries/cloudFormation/aws/elb_access_log_disabled/test/positive5.yaml @@ -0,0 +1,32 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: A simple EC2 instance +Resources: + MyLoadBalancer2: + Type: AWS::ElasticLoadBalancing::LoadBalancer + Properties: + AvailabilityZones: + - "us-east-2a" + CrossZone: "true" + Listeners: + - InstancePort: "80" + InstanceProtocol: HTTP + LoadBalancerPort: "443" + Protocol: HTTPS + PolicyNames: + - My-SSLNegotiation-Policy + SSLCertificateId: arn:aws:iam::123456789012:server-certificate/my-server-certificate + HealthCheck: + Target: HTTP:80/ + HealthyThreshold: "2" + UnhealthyThreshold: "3" + Interval: "10" + Timeout: "5" + Policies: + - PolicyName: My-SSLNegotiation-Policy + PolicyType: SSLNegotiationPolicyType + Attributes: + - Name: Reference-Security-Policy + Value: ELBSecurityPolicy-TLS-1-2-2017-01 + AccessLoggingPolicy: + Enabled: "false" + S3BucketName: teste diff --git a/assets/queries/cloudFormation/aws/elb_access_log_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/elb_access_log_disabled/test/positive_expected_result.json index cc94d643675..d4dfeba79a3 100644 --- a/assets/queries/cloudFormation/aws/elb_access_log_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/elb_access_log_disabled/test/positive_expected_result.json @@ -12,15 +12,21 @@ "fileName": "positive2.yaml" }, { - "fileName": "positive3.json", "queryName": "ELB Access Log Disabled", "severity": "MEDIUM", - "line": 7 + "line": 7, + "fileName": "positive3.json" }, { - "fileName": "positive4.json", "queryName": "ELB Access Log Disabled", "severity": "MEDIUM", - "line": 18 + "line": 18, + "fileName": "positive4.json" + }, + { + "queryName": "ELB Access Log Disabled", + "severity": "MEDIUM", + "line": 31, + "fileName": "positive5.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/elb_v2_alb_access_log_disabled/query.rego b/assets/queries/cloudFormation/aws/elb_v2_alb_access_log_disabled/query.rego index e12705e0737..24944aa6c60 100644 --- a/assets/queries/cloudFormation/aws/elb_v2_alb_access_log_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/elb_v2_alb_access_log_disabled/query.rego @@ -41,5 +41,5 @@ CxPolicy[result] { contains(arr, elem) { arr[i].Key == elem - arr[i].Value == false + cf_lib.isCloudFormationFalse(arr[i].Value) } diff --git a/assets/queries/cloudFormation/aws/elb_v2_alb_access_log_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/elb_v2_alb_access_log_disabled/test/negative3.yaml new file mode 100644 index 00000000000..20b90b76ffc --- /dev/null +++ b/assets/queries/cloudFormation/aws/elb_v2_alb_access_log_disabled/test/negative3.yaml @@ -0,0 +1,32 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: A simple EC2 instance +Parameters: + EnvironmentName: + Description: An environment name that will be prefixed to resource names + Type: String + + VPC: + Type: AWS::EC2::VPC::Id + Description: Choose which VPC the Application Load Balancer should be deployed to + + Subnets: + Description: Choose which subnets the Application Load Balancer should be deployed to + Type: List + + SecurityGroup: + Description: Select the Security Group to apply to the Application Load Balancer + Type: AWS::EC2::SecurityGroup::Id +Resources: + LoadBalancer: + Type: AWS::ElasticLoadBalancingV2::LoadBalancer + Properties: + Name: !Ref EnvironmentName + Subnets: !Ref Subnets + SecurityGroups: + - !Ref SecurityGroup + Tags: + - Key: Name + Value: !Ref EnvironmentName + LoadBalancerAttributes: + - Key: access_logs.s3.enabled + Value: "true" diff --git a/assets/queries/cloudFormation/aws/elb_v2_alb_access_log_disabled/test/positive5.yaml b/assets/queries/cloudFormation/aws/elb_v2_alb_access_log_disabled/test/positive5.yaml new file mode 100644 index 00000000000..77ca17f9768 --- /dev/null +++ b/assets/queries/cloudFormation/aws/elb_v2_alb_access_log_disabled/test/positive5.yaml @@ -0,0 +1,32 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: A simple EC2 instance +Parameters: + EnvironmentName: + Description: An environment name that will be prefixed to resource names + Type: String + + VPC: + Type: AWS::EC2::VPC::Id + Description: Choose which VPC the Application Load Balancer should be deployed to + + Subnets: + Description: Choose which subnets the Application Load Balancer should be deployed to + Type: List + + SecurityGroup: + Description: Select the Security Group to apply to the Application Load Balancer + Type: AWS::EC2::SecurityGroup::Id +Resources: + LoadBalancertest: + Type: AWS::ElasticLoadBalancingV2::LoadBalancer + Properties: + Name: !Ref EnvironmentName + Subnets: !Ref Subnets + SecurityGroups: + - !Ref SecurityGroup + Tags: + - Key: Name + Value: !Ref EnvironmentName + LoadBalancerAttributes: + - Key: access_logs.s3.enabled + Value: "false" diff --git a/assets/queries/cloudFormation/aws/elb_v2_alb_access_log_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/elb_v2_alb_access_log_disabled/test/positive_expected_result.json index 2e7794dd5f7..37ff9f3c3f4 100644 --- a/assets/queries/cloudFormation/aws/elb_v2_alb_access_log_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/elb_v2_alb_access_log_disabled/test/positive_expected_result.json @@ -22,5 +22,11 @@ "severity": "MEDIUM", "line": 36, "fileName": "positive4.json" + }, + { + "queryName": "ELBv2 ALB Access Log Disabled", + "severity": "MEDIUM", + "line": 30, + "fileName": "positive5.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/emr_security_configuration_encryptions_enabled/query.rego b/assets/queries/cloudFormation/aws/emr_security_configuration_encryptions_enabled/query.rego index 5986f158237..86f473aec92 100644 --- a/assets/queries/cloudFormation/aws/emr_security_configuration_encryptions_enabled/query.rego +++ b/assets/queries/cloudFormation/aws/emr_security_configuration_encryptions_enabled/query.rego @@ -9,7 +9,7 @@ CxPolicy[result] { resource.Type == "AWS::EMR::SecurityConfiguration" properties := resource.Properties - properties.SecurityConfiguration.EncryptionConfiguration.AtRestEncryptionConfiguration.LocalDiskEncryptionConfiguration.EnableEbsEncryption == false + cf_lib.isCloudFormationFalse(properties.SecurityConfiguration.EncryptionConfiguration.AtRestEncryptionConfiguration.LocalDiskEncryptionConfiguration.EnableEbsEncryption) result := { "documentId": input.document[i].id, @@ -28,7 +28,7 @@ CxPolicy[result] { resource.Type == "AWS::EMR::SecurityConfiguration" properties := resource.Properties - properties.SecurityConfiguration.EncryptionConfiguration.EnableInTransitEncryption == false + cf_lib.isCloudFormationFalse(properties.SecurityConfiguration.EncryptionConfiguration.EnableInTransitEncryption) result := { "documentId": input.document[i].id, @@ -47,7 +47,7 @@ CxPolicy[result] { resource.Type == "AWS::EMR::SecurityConfiguration" properties := resource.Properties - properties.SecurityConfiguration.EncryptionConfiguration.EnableAtRestEncryption == false + cf_lib.isCloudFormationFalse(properties.SecurityConfiguration.EncryptionConfiguration.EnableAtRestEncryption) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/emr_security_configuration_encryptions_enabled/test/negative7.yaml b/assets/queries/cloudFormation/aws/emr_security_configuration_encryptions_enabled/test/negative7.yaml new file mode 100644 index 00000000000..2746f5f2b91 --- /dev/null +++ b/assets/queries/cloudFormation/aws/emr_security_configuration_encryptions_enabled/test/negative7.yaml @@ -0,0 +1,16 @@ +#this code is a correct code for which the query should not find any result +#this is a problematic code where the query should report a result(s) +Resources: + EMRSecurityConfiguration: + Type: AWS::EMR::SecurityConfiguration + Properties: + Name: String + SecurityConfiguration: + EncryptionConfiguration: + EnableInTransitEncryption: "true" + EnableAtRestEncryption: "true" + AtRestEncryptionConfiguration: + LocalDiskEncryptionConfiguration: + EnableEbsEncryption: "true" + EncryptionKeyProviderType: AwsKms + AwsKmsKey: arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012 diff --git a/assets/queries/cloudFormation/aws/emr_security_configuration_encryptions_enabled/test/positive9.yaml b/assets/queries/cloudFormation/aws/emr_security_configuration_encryptions_enabled/test/positive9.yaml new file mode 100644 index 00000000000..f1ef2d16092 --- /dev/null +++ b/assets/queries/cloudFormation/aws/emr_security_configuration_encryptions_enabled/test/positive9.yaml @@ -0,0 +1,14 @@ +Resources: + EMRSecurityConfiguration: + Type: AWS::EMR::SecurityConfiguration + Properties: + Name: String + SecurityConfiguration: + EncryptionConfiguration: + EnableInTransitEncryption: "false" + EnableAtRestEncryption: "false" + AtRestEncryptionConfiguration: + LocalDiskEncryptionConfiguration: + EnableEbsEncryption: "true" + EncryptionKeyProviderType: AwsKms + AwsKmsKey: arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012 diff --git a/assets/queries/cloudFormation/aws/emr_security_configuration_encryptions_enabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/emr_security_configuration_encryptions_enabled/test/positive_expected_result.json index 9c55aa38e4d..69b2e0f60fa 100644 --- a/assets/queries/cloudFormation/aws/emr_security_configuration_encryptions_enabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/emr_security_configuration_encryptions_enabled/test/positive_expected_result.json @@ -2,74 +2,74 @@ { "queryName": "EMR Security Configuration Encryption Disabled", "severity": "MEDIUM", - "line": 10, - "fileName": "positive2.yaml" + "line": 8, + "fileName": "positive1.yaml" }, { "queryName": "EMR Security Configuration Encryption Disabled", "severity": "MEDIUM", - "line": 8, + "line": 9, "fileName": "positive1.yaml" }, { "queryName": "EMR Security Configuration Encryption Disabled", "severity": "MEDIUM", - "line": 8, - "fileName": "positive3.yaml" + "line": 9, + "fileName": "positive2.yaml" }, { - "fileName": "positive1.yaml", "queryName": "EMR Security Configuration Encryption Disabled", "severity": "MEDIUM", - "line": 9 + "line": 10, + "fileName": "positive2.yaml" }, { "queryName": "EMR Security Configuration Encryption Disabled", "severity": "MEDIUM", - "line": 9, + "line": 8, "fileName": "positive3.yaml" }, { "queryName": "EMR Security Configuration Encryption Disabled", "severity": "MEDIUM", "line": 9, - "fileName": "positive2.yaml" + "fileName": "positive3.yaml" }, { + "queryName": "EMR Security Configuration Encryption Disabled", "severity": "MEDIUM", "line": 6, - "fileName": "positive4.yaml", - "queryName": "EMR Security Configuration Encryption Disabled" + "fileName": "positive4.yaml" }, { - "fileName": "positive5.json", "queryName": "EMR Security Configuration Encryption Disabled", "severity": "MEDIUM", - "line": 9 + "line": 9, + "fileName": "positive5.json" }, { - "fileName": "positive5.json", "queryName": "EMR Security Configuration Encryption Disabled", "severity": "MEDIUM", - "line": 10 + "line": 10, + "fileName": "positive5.json" }, { "queryName": "EMR Security Configuration Encryption Disabled", "severity": "MEDIUM", - "line": 10, + "line": 9, "fileName": "positive6.json" }, { "queryName": "EMR Security Configuration Encryption Disabled", "severity": "MEDIUM", - "line": 9, + "line": 10, "fileName": "positive6.json" }, { - "line": 8, - "fileName": "positive7.json", "queryName": "EMR Security Configuration Encryption Disabled", - "severity": "MEDIUM" + "severity": "MEDIUM", + "line": 8, + "fileName": "positive7.json" }, { "queryName": "EMR Security Configuration Encryption Disabled", @@ -82,5 +82,17 @@ "severity": "MEDIUM", "line": 7, "fileName": "positive8.json" + }, + { + "queryName": "EMR Security Configuration Encryption Disabled", + "severity": "MEDIUM", + "line": 8, + "fileName": "positive9.yaml" + }, + { + "queryName": "EMR Security Configuration Encryption Disabled", + "severity": "MEDIUM", + "line": 9, + "fileName": "positive9.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/github_repository_set_to_public/query.rego b/assets/queries/cloudFormation/aws/github_repository_set_to_public/query.rego index 9a88d99b083..92ac4659a59 100644 --- a/assets/queries/cloudFormation/aws/github_repository_set_to_public/query.rego +++ b/assets/queries/cloudFormation/aws/github_repository_set_to_public/query.rego @@ -26,7 +26,7 @@ CxPolicy[result] { resource.Type == "AWS::CodeStar::GitHubRepository" - resource.Properties.IsPrivate != true + not cf_lib.isCloudFormationTrue(resource.Properties.IsPrivate) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/github_repository_set_to_public/test/negative1.yaml b/assets/queries/cloudFormation/aws/github_repository_set_to_public/test/negative1.yaml index 9f5db6465e8..3307d0bc682 100644 --- a/assets/queries/cloudFormation/aws/github_repository_set_to_public/test/negative1.yaml +++ b/assets/queries/cloudFormation/aws/github_repository_set_to_public/test/negative1.yaml @@ -8,8 +8,8 @@ Resources: Bucket: "my-bucket" Key: "sourcecode.zip" ObjectVersion: "1" - EnableIssues: true - IsPrivate: true + EnableIssues: "true" + IsPrivate: "true" RepositoryAccessToken: '{{resolve:secretsmanager:your-secret-manager-name:SecretString:your-secret-manager-key}}' RepositoryDescription: a description RepositoryName: my-github-repo diff --git a/assets/queries/cloudFormation/aws/github_repository_set_to_public/test/negative3.yaml b/assets/queries/cloudFormation/aws/github_repository_set_to_public/test/negative3.yaml new file mode 100644 index 00000000000..9f5db6465e8 --- /dev/null +++ b/assets/queries/cloudFormation/aws/github_repository_set_to_public/test/negative3.yaml @@ -0,0 +1,16 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + MyRepo1: + Type: AWS::CodeStar::GitHubRepository + Properties: + Code: + S3: + Bucket: "my-bucket" + Key: "sourcecode.zip" + ObjectVersion: "1" + EnableIssues: true + IsPrivate: true + RepositoryAccessToken: '{{resolve:secretsmanager:your-secret-manager-name:SecretString:your-secret-manager-key}}' + RepositoryDescription: a description + RepositoryName: my-github-repo + RepositoryOwner: my-github-account diff --git a/assets/queries/cloudFormation/aws/github_repository_set_to_public/test/positive5.yaml b/assets/queries/cloudFormation/aws/github_repository_set_to_public/test/positive5.yaml new file mode 100644 index 00000000000..08f181232ba --- /dev/null +++ b/assets/queries/cloudFormation/aws/github_repository_set_to_public/test/positive5.yaml @@ -0,0 +1,16 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + MyRepo3: + Type: AWS::CodeStar::GitHubRepository + Properties: + Code: + S3: + Bucket: "my-bucket" + Key: "sourcecode.zip" + ObjectVersion: "1" + EnableIssues: "true" + IsPrivate: "false" + RepositoryAccessToken: '{{resolve:secretsmanager:your-secret-manager-name:SecretString:your-secret-manager-key}}' + RepositoryDescription: a description + RepositoryName: my-github-repo + RepositoryOwner: my-github-account diff --git a/assets/queries/cloudFormation/aws/github_repository_set_to_public/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/github_repository_set_to_public/test/positive_expected_result.json index 794892178a9..865819ed241 100644 --- a/assets/queries/cloudFormation/aws/github_repository_set_to_public/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/github_repository_set_to_public/test/positive_expected_result.json @@ -6,21 +6,27 @@ "fileName": "positive1.yaml" }, { - "fileName": "positive3.json", "queryName": "GitHub Repository Set To Public", "severity": "MEDIUM", - "line": 5 + "line": 5, + "fileName": "positive3.json" }, { - "fileName": "positive2.yaml", "queryName": "GitHub Repository Set To Public", "severity": "MEDIUM", - "line": 5 + "line": 5, + "fileName": "positive2.yaml" }, { - "fileName": "positive4.json", "queryName": "GitHub Repository Set To Public", "severity": "MEDIUM", - "line": 14 + "line": 14, + "fileName": "positive4.json" + }, + { + "queryName": "GitHub Repository Set To Public", + "severity": "MEDIUM", + "line": 12, + "fileName": "positive5.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/guardduty_detector_disabled/query.rego b/assets/queries/cloudFormation/aws/guardduty_detector_disabled/query.rego index 5bc1b825a9b..51d64cee2c2 100644 --- a/assets/queries/cloudFormation/aws/guardduty_detector_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/guardduty_detector_disabled/query.rego @@ -6,7 +6,7 @@ CxPolicy[result] { resource := input.document[i].Resources[name] resource.Type == "AWS::GuardDuty::Detector" properties := resource.Properties - properties.Enable == false + cf_lib.isCloudFormationFalse(properties.Enable) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/guardduty_detector_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/guardduty_detector_disabled/test/negative3.yaml new file mode 100644 index 00000000000..ea4b263e433 --- /dev/null +++ b/assets/queries/cloudFormation/aws/guardduty_detector_disabled/test/negative3.yaml @@ -0,0 +1,7 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + mydetector: + Type: AWS::GuardDuty::Detector + Properties: + Enable: "True" + FindingPublishingFrequency: FIFTEEN_MINUTES diff --git a/assets/queries/cloudFormation/aws/guardduty_detector_disabled/test/positive3.yaml b/assets/queries/cloudFormation/aws/guardduty_detector_disabled/test/positive3.yaml new file mode 100644 index 00000000000..2acc068fc8a --- /dev/null +++ b/assets/queries/cloudFormation/aws/guardduty_detector_disabled/test/positive3.yaml @@ -0,0 +1,7 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + mydetector3: + Type: AWS::GuardDuty::Detector + Properties: + Enable: "False" + FindingPublishingFrequency: FIFTEEN_MINUTES diff --git a/assets/queries/cloudFormation/aws/guardduty_detector_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/guardduty_detector_disabled/test/positive_expected_result.json index ffdbde55cea..31c42b15f5e 100644 --- a/assets/queries/cloudFormation/aws/guardduty_detector_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/guardduty_detector_disabled/test/positive_expected_result.json @@ -10,5 +10,11 @@ "severity": "MEDIUM", "line": 6, "fileName": "positive2.json" + }, + { + "queryName": "GuardDuty Detector Disabled", + "severity": "MEDIUM", + "line": 6, + "fileName": "positive3.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/iam_database_auth_not_enabled/query.rego b/assets/queries/cloudFormation/aws/iam_database_auth_not_enabled/query.rego index 92da74ce968..553ce5ea044 100644 --- a/assets/queries/cloudFormation/aws/iam_database_auth_not_enabled/query.rego +++ b/assets/queries/cloudFormation/aws/iam_database_auth_not_enabled/query.rego @@ -9,7 +9,7 @@ CxPolicy[result] { resource := Resources[name] resource.Type == "AWS::RDS::DBInstance" properties := resource.Properties - properties.EnableIAMDatabaseAuthentication == false + cf_lib.isCloudFormationFalse(properties.EnableIAMDatabaseAuthentication) common_lib.valid_for_iam_engine_and_version_check(properties, "Engine", "EngineVersion", "DBInstanceClass") result := { diff --git a/assets/queries/cloudFormation/aws/iam_database_auth_not_enabled/test/negative5.yaml b/assets/queries/cloudFormation/aws/iam_database_auth_not_enabled/test/negative5.yaml new file mode 100644 index 00000000000..4a0cca1fcfd --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_database_auth_not_enabled/test/negative5.yaml @@ -0,0 +1,19 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: RDS Storage Encrypted +Parameters: + SourceDBInstanceIdentifier: + Type: String + DBInstanceType: + Type: String + SourceRegion: + Type: String +Resources: + MyDBSmall: + Type: "AWS::RDS::DBInstance" + Properties: + DBInstanceClass: !Ref DBInstanceType + SourceDBInstanceIdentifier: !Ref SourceDBInstanceIdentifier + SourceRegion: !Ref SourceRegion + DeletionProtection: "false" + KmsKeyId: !Ref MyKey + EnableIAMDatabaseAuthentication: "true" diff --git a/assets/queries/cloudFormation/aws/iam_database_auth_not_enabled/test/positive5.yaml b/assets/queries/cloudFormation/aws/iam_database_auth_not_enabled/test/positive5.yaml new file mode 100644 index 00000000000..5a96618d05f --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_database_auth_not_enabled/test/positive5.yaml @@ -0,0 +1,20 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: RDS Storage Encrypted +Parameters: + SourceDBInstanceIdentifier: + Type: String + DBInstanceType: + Type: String + SourceRegion: + Type: String +Resources: + MyDBSmall: + Type: "AWS::RDS::DBInstance" + Properties: + DBInstanceClass: db.r3.xlarge + SourceDBInstanceIdentifier: !Ref SourceDBInstanceIdentifier + SourceRegion: !Ref SourceRegion + DeletionProtection: "false" + KmsKeyId: !Ref MyKey + EnableIAMDatabaseAuthentication: "false" + Engine: aurora diff --git a/assets/queries/cloudFormation/aws/iam_database_auth_not_enabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/iam_database_auth_not_enabled/test/positive_expected_result.json index 09d1d7f20e2..9d7881e32ef 100644 --- a/assets/queries/cloudFormation/aws/iam_database_auth_not_enabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/iam_database_auth_not_enabled/test/positive_expected_result.json @@ -18,9 +18,15 @@ "fileName": "positive3.yaml" }, { - "fileName": "positive4.json", "queryName": "IAM Database Auth Not Enabled", "severity": "MEDIUM", - "line": 18 + "line": 18, + "fileName": "positive4.json" + }, + { + "queryName": "IAM Database Auth Not Enabled", + "severity": "MEDIUM", + "line": 19, + "fileName": "positive5.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/kms_enable_key_rotation_disabled/query.rego b/assets/queries/cloudFormation/aws/kms_enable_key_rotation_disabled/query.rego index f5f89398300..0f4f89c21c4 100644 --- a/assets/queries/cloudFormation/aws/kms_enable_key_rotation_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/kms_enable_key_rotation_disabled/query.rego @@ -6,8 +6,7 @@ import data.generic.cloudformation as cf_lib CxPolicy[result] { resources := input.document[i].Resources[name] resources.Type == "AWS::KMS::Key" - keyRotation := resources.Properties.EnableKeyRotation - keyRotation == false + cf_lib.isCloudFormationFalse(resources.Properties.EnableKeyRotation) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/kms_enable_key_rotation_disabled/test/negative1.yaml b/assets/queries/cloudFormation/aws/kms_enable_key_rotation_disabled/test/negative1.yaml index 830fce69bc9..fb06aef80fb 100644 --- a/assets/queries/cloudFormation/aws/kms_enable_key_rotation_disabled/test/negative1.yaml +++ b/assets/queries/cloudFormation/aws/kms_enable_key_rotation_disabled/test/negative1.yaml @@ -5,7 +5,7 @@ Resources: Type: AWS::KMS::Key Properties: Description: An example symmetric CMK - EnableKeyRotation: True + EnableKeyRotation: "True" KeyPolicy: Version: '2012-10-17' Id: key-default-1 diff --git a/assets/queries/cloudFormation/aws/kms_enable_key_rotation_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/kms_enable_key_rotation_disabled/test/negative3.yaml new file mode 100644 index 00000000000..830fce69bc9 --- /dev/null +++ b/assets/queries/cloudFormation/aws/kms_enable_key_rotation_disabled/test/negative3.yaml @@ -0,0 +1,48 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: A sample template +Resources: + myKey: + Type: AWS::KMS::Key + Properties: + Description: An example symmetric CMK + EnableKeyRotation: True + KeyPolicy: + Version: '2012-10-17' + Id: key-default-1 + Statement: + - Sid: Enable IAM User Permissions + Effect: Allow + Principal: + AWS: arn:aws:iam::111122223333:root + Action: kms:* + Resource: '*' + - Sid: Allow administration of the key + Effect: Allow + Principal: + AWS: arn:aws:iam::123456789012:user/Alice + Action: + - kms:Create* + - kms:Describe* + - kms:Enable* + - kms:List* + - kms:Put* + - kms:Update* + - kms:Revoke* + - kms:Disable* + - kms:Get* + - kms:Delete* + - kms:ScheduleKeyDeletion + - kms:CancelKeyDeletion + Resource: '*' + - Sid: Allow use of the key + Effect: Allow + Principal: + AWS: arn:aws:iam::123456789012:user/Bob + Action: + - kms:DescribeKey + - kms:Encrypt + - kms:Decrypt + - kms:ReEncrypt* + - kms:GenerateDataKey + - kms:GenerateDataKeyWithoutPlaintext + Resource: '*' \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/kms_enable_key_rotation_disabled/test/positive3.yaml b/assets/queries/cloudFormation/aws/kms_enable_key_rotation_disabled/test/positive3.yaml new file mode 100644 index 00000000000..af10c19512d --- /dev/null +++ b/assets/queries/cloudFormation/aws/kms_enable_key_rotation_disabled/test/positive3.yaml @@ -0,0 +1,92 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: A sample template +Resources: + myKey: + Type: AWS::KMS::Key + Properties: + Description: An example symmetric CMK + EnableKeyRotation: "false" + KeyPolicy: + Version: '2012-10-17' + Id: key-default-1 + Statement: + - Sid: Enable IAM User Permissions + Effect: Allow + Principal: + AWS: arn:aws:iam::111122223333:root + Action: kms:* + Resource: '*' + - Sid: Allow administration of the key + Effect: Allow + Principal: + AWS: arn:aws:iam::123456789012:user/Alice + Action: + - kms:Create* + - kms:Describe* + - kms:Enable* + - kms:List* + - kms:Put* + - kms:Update* + - kms:Revoke* + - kms:Disable* + - kms:Get* + - kms:Delete* + - kms:ScheduleKeyDeletion + - kms:CancelKeyDeletion + Resource: '*' + - Sid: Allow use of the key + Effect: Allow + Principal: + AWS: arn:aws:iam::123456789012:user/Bob + Action: + - kms:DescribeKey + - kms:Encrypt + - kms:Decrypt + - kms:ReEncrypt* + - kms:GenerateDataKey + - kms:GenerateDataKeyWithoutPlaintext + Resource: '*' + myKey2: + Type: AWS::KMS::Key + Properties: + Description: An example symmetric CMK + KeyPolicy: + Version: '2012-10-17' + Id: key-default-1 + Statement: + - Sid: Enable IAM User Permissions + Effect: Allow + Principal: + AWS: arn:aws:iam::111122223333:root + Action: kms:* + Resource: '*' + - Sid: Allow administration of the key + Effect: Allow + Principal: + AWS: arn:aws:iam::123456789012:user/Alice + Action: + - kms:Create* + - kms:Describe* + - kms:Enable* + - kms:List* + - kms:Put* + - kms:Update* + - kms:Revoke* + - kms:Disable* + - kms:Get* + - kms:Delete* + - kms:ScheduleKeyDeletion + - kms:CancelKeyDeletion + Resource: '*' + - Sid: Allow use of the key + Effect: Allow + Principal: + AWS: arn:aws:iam::123456789012:user/Bob + Action: + - kms:DescribeKey + - kms:Encrypt + - kms:Decrypt + - kms:ReEncrypt* + - kms:GenerateDataKey + - kms:GenerateDataKeyWithoutPlaintext + Resource: '*' \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/kms_enable_key_rotation_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/kms_enable_key_rotation_disabled/test/positive_expected_result.json index 842e5853f35..4482b431b9a 100644 --- a/assets/queries/cloudFormation/aws/kms_enable_key_rotation_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/kms_enable_key_rotation_disabled/test/positive_expected_result.json @@ -1,26 +1,38 @@ [ { - "line": 8, - "fileName": "positive1.yaml", "queryName": "KMS Key Rotation Disabled", - "severity": "MEDIUM" + "severity": "MEDIUM", + "line": 8, + "fileName": "positive1.yaml" }, { + "queryName": "KMS Key Rotation Disabled", "severity": "MEDIUM", "line": 51, - "fileName": "positive1.yaml", - "queryName": "KMS Key Rotation Disabled" + "fileName": "positive1.yaml" }, { + "queryName": "KMS Key Rotation Disabled", "severity": "MEDIUM", "line": 60, - "fileName": "positive2.json", - "queryName": "KMS Key Rotation Disabled" + "fileName": "positive2.json" }, { "queryName": "KMS Key Rotation Disabled", "severity": "MEDIUM", "line": 65, "fileName": "positive2.json" + }, + { + "queryName": "KMS Key Rotation Disabled", + "severity": "MEDIUM", + "line": 8, + "fileName": "positive3.yaml" + }, + { + "queryName": "KMS Key Rotation Disabled", + "severity": "MEDIUM", + "line": 51, + "fileName": "positive3.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/mq_broker_is_publicly_accessible/query.rego b/assets/queries/cloudFormation/aws/mq_broker_is_publicly_accessible/query.rego index 5c55c718f5b..6012f8ed917 100644 --- a/assets/queries/cloudFormation/aws/mq_broker_is_publicly_accessible/query.rego +++ b/assets/queries/cloudFormation/aws/mq_broker_is_publicly_accessible/query.rego @@ -7,8 +7,8 @@ CxPolicy[result] { resource = document[i].Resources[name] resource.Type == "AWS::AmazonMQ::Broker" properties := resource.Properties - - properties.PubliclyAccessible + + cf_lib.isCloudFormationTrue(properties.PubliclyAccessible) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/mq_broker_is_publicly_accessible/test/negative3.yaml b/assets/queries/cloudFormation/aws/mq_broker_is_publicly_accessible/test/negative3.yaml new file mode 100644 index 00000000000..de0194c5eb4 --- /dev/null +++ b/assets/queries/cloudFormation/aws/mq_broker_is_publicly_accessible/test/negative3.yaml @@ -0,0 +1,24 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "Create a basic ActiveMQ broker" +Resources: + BasicBroker: + Type: "AWS::AmazonMQ::Broker" + Properties: + AutoMinorVersionUpgrade: "false" + BrokerName: MyBasicBroker + DeploymentMode: SINGLE_INSTANCE + EncryptionOptions: + UseAwsOwnedKey: "true" + EngineType: ActiveMQ + EngineVersion: "5.15.0" + HostInstanceType: mq.t2.micro + PubliclyAccessible: "false" + Users: + - + ConsoleAccess: "true" + Groups: + - MyGroup + Password: + Ref: "BrokerPassword" + Username: + Ref: "BrokerUsername" diff --git a/assets/queries/cloudFormation/aws/mq_broker_is_publicly_accessible/test/positive3.yaml b/assets/queries/cloudFormation/aws/mq_broker_is_publicly_accessible/test/positive3.yaml new file mode 100644 index 00000000000..7ec0732aee6 --- /dev/null +++ b/assets/queries/cloudFormation/aws/mq_broker_is_publicly_accessible/test/positive3.yaml @@ -0,0 +1,24 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "Create a basic ActiveMQ broker" +Resources: + BasicBroker: + Type: "AWS::AmazonMQ::Broker" + Properties: + AutoMinorVersionUpgrade: "false" + BrokerName: MyBasicBroker + DeploymentMode: SINGLE_INSTANCE + EncryptionOptions: + UseAwsOwnedKey: "true" + EngineType: ActiveMQ + EngineVersion: "5.15.0" + HostInstanceType: mq.t2.micro + PubliclyAccessible: "true" + Users: + - + ConsoleAccess: "true" + Groups: + - MyGroup + Password: + Ref: "BrokerPassword" + Username: + Ref: "BrokerUsername" diff --git a/assets/queries/cloudFormation/aws/mq_broker_is_publicly_accessible/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/mq_broker_is_publicly_accessible/test/positive_expected_result.json index 28e66f7364d..501f3544d25 100644 --- a/assets/queries/cloudFormation/aws/mq_broker_is_publicly_accessible/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/mq_broker_is_publicly_accessible/test/positive_expected_result.json @@ -10,5 +10,11 @@ "severity": "HIGH", "line": 31, "fileName": "positive2.json" + }, + { + "queryName": "MQ Broker Is Publicly Accessible", + "severity": "HIGH", + "line": 15, + "fileName": "positive3.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/mq_broker_logging_disabled/query.rego b/assets/queries/cloudFormation/aws/mq_broker_logging_disabled/query.rego index e536d783fed..efae876a6bc 100644 --- a/assets/queries/cloudFormation/aws/mq_broker_logging_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/mq_broker_logging_disabled/query.rego @@ -53,7 +53,7 @@ CxPolicy[result] { logTypes := ["Audit","General"] common_lib.valid_key(properties.Logs,logTypes[j]) - properties.Logs[logTypes[j]] == false + cf_lib.isCloudFormationFalse(properties.Logs[logTypes[j]]) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/mq_broker_logging_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/mq_broker_logging_disabled/test/negative3.yaml new file mode 100644 index 00000000000..b3319871187 --- /dev/null +++ b/assets/queries/cloudFormation/aws/mq_broker_logging_disabled/test/negative3.yaml @@ -0,0 +1,27 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "Create a basic ActiveMQ broker" +Resources: + BasicBroker: + Type: "AWS::AmazonMQ::Broker" + Properties: + AutoMinorVersionUpgrade: "false" + BrokerName: MyBasicBroker + DeploymentMode: SINGLE_INSTANCE + EncryptionOptions: + UseAwsOwnedKey: "true" + EngineType: ActiveMQ + EngineVersion: "5.15.0" + HostInstanceType: mq.t2.micro + PubliclyAccessible: "false" + Users: + - + ConsoleAccess: "true" + Groups: + - MyGroup + Password: + Ref: "BrokerPassword" + Username: + Ref: "BrokerUsername" + Logs: + General: "true" + Audit: "true" diff --git a/assets/queries/cloudFormation/aws/mq_broker_logging_disabled/test/positive3.yaml b/assets/queries/cloudFormation/aws/mq_broker_logging_disabled/test/positive3.yaml new file mode 100644 index 00000000000..9a291c0596e --- /dev/null +++ b/assets/queries/cloudFormation/aws/mq_broker_logging_disabled/test/positive3.yaml @@ -0,0 +1,103 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "Create a basic ActiveMQ broker" +Resources: + BasicBroker3: + Type: "AWS::AmazonMQ::Broker" + Properties: + BrokerName: MyBasicBroker + DeploymentMode: SINGLE_INSTANCE + EngineType: ActiveMQ + EngineVersion: "5.15.0" + HostInstanceType: mq.t2.micro + PubliclyAccessible: "false" + Users: + - + ConsoleAccess: "true" + Groups: + - MyGroup + Password: + Ref: "BrokerPassword" + Username: + Ref: "BrokerUsername" + Logs: + General: "true" + BasicBroker4: + Type: "AWS::AmazonMQ::Broker" + Properties: + BrokerName: MyBasicBroker + DeploymentMode: SINGLE_INSTANCE + EngineType: ActiveMQ + EngineVersion: "5.15.0" + HostInstanceType: mq.t2.micro + PubliclyAccessible: "false" + Users: + - + ConsoleAccess: "true" + Groups: + - MyGroup + Password: + Ref: "BrokerPassword" + Username: + Ref: "BrokerUsername" + Logs: + Audit: "true" + BasicBroker5: + Type: "AWS::AmazonMQ::Broker" + Properties: + BrokerName: MyBasicBroker + DeploymentMode: SINGLE_INSTANCE + EngineType: ActiveMQ + EngineVersion: "5.15.0" + HostInstanceType: mq.t2.micro + PubliclyAccessible: "false" + Users: + - + ConsoleAccess: "true" + Groups: + - MyGroup + Password: + Ref: "BrokerPassword" + Username: + Ref: "BrokerUsername" + Logs: + General: "false" + Audit: "true" + BasicBroker6: + Type: "AWS::AmazonMQ::Broker" + Properties: + BrokerName: MyBasicBroker + DeploymentMode: SINGLE_INSTANCE + EngineType: ActiveMQ + EngineVersion: "5.15.0" + HostInstanceType: mq.t2.micro + PubliclyAccessible: "false" + Users: + - + ConsoleAccess: "true" + Groups: + - MyGroup + Password: + Ref: "BrokerPassword" + Username: + Ref: "BrokerUsername" + Logs: + Audit: "false" + General: "true" + BasicBroker7: + Type: "AWS::AmazonMQ::Broker" + Properties: + BrokerName: MyBasicBroker + DeploymentMode: SINGLE_INSTANCE + EngineType: ActiveMQ + EngineVersion: "5.15.0" + HostInstanceType: mq.t2.micro + PubliclyAccessible: "false" + Users: + - + ConsoleAccess: "true" + Groups: + - MyGroup + Password: + Ref: "BrokerPassword" + Username: + Ref: "BrokerUsername" diff --git a/assets/queries/cloudFormation/aws/mq_broker_logging_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/mq_broker_logging_disabled/test/positive_expected_result.json index 19c74749c46..aafc2fcd845 100644 --- a/assets/queries/cloudFormation/aws/mq_broker_logging_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/mq_broker_logging_disabled/test/positive_expected_result.json @@ -58,5 +58,35 @@ "severity": "MEDIUM", "line": 121, "fileName": "positive2.json" + }, + { + "queryName": "MQ Broker Logging Disabled", + "severity": "MEDIUM", + "line": 22, + "fileName": "positive5.yaml" + }, + { + "queryName": "MQ Broker Logging Disabled", + "severity": "MEDIUM", + "line": 42, + "fileName": "positive5.yaml" + }, + { + "queryName": "MQ Broker Logging Disabled", + "severity": "MEDIUM", + "line": 63, + "fileName": "positive5.yaml" + }, + { + "queryName": "MQ Broker Logging Disabled", + "severity": "MEDIUM", + "line": 84, + "fileName": "positive5.yaml" + }, + { + "queryName": "MQ Broker Logging Disabled", + "severity": "MEDIUM", + "line": 88, + "fileName": "positive5.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/msk_cluster_encryption_disabled/query.rego b/assets/queries/cloudFormation/aws/msk_cluster_encryption_disabled/query.rego index 6c4a7c1e66f..32e4e5152c7 100644 --- a/assets/queries/cloudFormation/aws/msk_cluster_encryption_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/msk_cluster_encryption_disabled/query.rego @@ -47,7 +47,7 @@ CxPolicy[result] { resource.Type == "AWS::MSK::Cluster" properties := resource.Properties - isResFalse(properties.EncryptionInfo.EncryptionInTransit.InCluster) + cf_lib.isCloudFormationFalse(properties.EncryptionInfo.EncryptionInTransit.InCluster) result := { "documentId": input.document[i].id, @@ -60,8 +60,3 @@ CxPolicy[result] { } } -isResFalse(answer) { - answer == "false" -} else { - answer == false -} diff --git a/assets/queries/cloudFormation/aws/msk_cluster_logging_disabled/query.rego b/assets/queries/cloudFormation/aws/msk_cluster_logging_disabled/query.rego index 42018cee76b..704d06413de 100644 --- a/assets/queries/cloudFormation/aws/msk_cluster_logging_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/msk_cluster_logging_disabled/query.rego @@ -64,5 +64,5 @@ CxPolicy[result] { } func(logs) { - logs[_].Enabled == true + cf_lib.isCloudFormationTrue(logs[_].Enabled) } diff --git a/assets/queries/cloudFormation/aws/msk_cluster_logging_disabled/test/negative5.yaml b/assets/queries/cloudFormation/aws/msk_cluster_logging_disabled/test/negative5.yaml new file mode 100644 index 00000000000..ea9cb2a642f --- /dev/null +++ b/assets/queries/cloudFormation/aws/msk_cluster_logging_disabled/test/negative5.yaml @@ -0,0 +1,23 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: MSK Cluster with required properties. +Resources: + TestCluster2: + Type: 'AWS::MSK::Cluster' + Properties: + ClusterName: ClusterWithRequiredProperties + KafkaVersion: 2.2.1 + LoggingInfo: + BrokerLogs: + CloudWatchLogs: + Enabled: "false" + LogGroup: aws_cloudwatch_log_group.test.name + S3: + Enabled: "true" + LogGroup: s3.test.name + NumberOfBrokerNodes: 3 + BrokerNodeGroupInfo: + InstanceType: kafka.m5.large + ClientSubnets: + - ReplaceWithSubnetId1 + - ReplaceWithSubnetId2 + - ReplaceWithSubnetId3 diff --git a/assets/queries/cloudFormation/aws/msk_cluster_logging_disabled/test/positive7.yaml b/assets/queries/cloudFormation/aws/msk_cluster_logging_disabled/test/positive7.yaml new file mode 100644 index 00000000000..2fe9e39c8a6 --- /dev/null +++ b/assets/queries/cloudFormation/aws/msk_cluster_logging_disabled/test/positive7.yaml @@ -0,0 +1,26 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: MSK Cluster with required properties. +Resources: + TestCluster6: + Type: 'AWS::MSK::Cluster' + Properties: + ClusterName: ClusterWithRequiredProperties + KafkaVersion: 2.2.1 + LoggingInfo: + BrokerLogs: + CloudWatchLogs: + Enabled: "false" + LogGroup: aws_cloudwatch_log_group.test.name + Firehose: + Enabled: "false" + LogGroup: firehose.test.name + S3: + Enabled: "false" + LogGroup: s3.test.name + NumberOfBrokerNodes: 3 + BrokerNodeGroupInfo: + InstanceType: kafka.m5.large + ClientSubnets: + - ReplaceWithSubnetId1 + - ReplaceWithSubnetId2 + - ReplaceWithSubnetId3 diff --git a/assets/queries/cloudFormation/aws/msk_cluster_logging_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/msk_cluster_logging_disabled/test/positive_expected_result.json index ece4beb1ca4..18936d80396 100644 --- a/assets/queries/cloudFormation/aws/msk_cluster_logging_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/msk_cluster_logging_disabled/test/positive_expected_result.json @@ -1,62 +1,80 @@ [ { + "queryName": "MSK Cluster Logging Disabled", + "severity": "MEDIUM", "line": 6, - "fileName": "positive1.yaml", + "fileName": "positive1.yaml" + }, + { "queryName": "MSK Cluster Logging Disabled", - "severity": "MEDIUM" + "severity": "MEDIUM", + "line": 12, + "fileName": "positive2.yaml" }, { - "line": 7, - "fileName": "positive4.json", "queryName": "MSK Cluster Logging Disabled", - "severity": "MEDIUM" + "severity": "MEDIUM", + "line": 15, + "fileName": "positive2.yaml" }, { - "line": 12, - "fileName": "positive2.yaml", "queryName": "MSK Cluster Logging Disabled", - "severity": "MEDIUM" + "severity": "MEDIUM", + "line": 18, + "fileName": "positive2.yaml" }, { - "line": 15, - "fileName": "positive2.yaml", "queryName": "MSK Cluster Logging Disabled", - "severity": "MEDIUM" + "severity": "MEDIUM", + "line": 12, + "fileName": "positive3.yaml" }, { - "line": 18, - "fileName": "positive2.yaml", "queryName": "MSK Cluster Logging Disabled", - "severity": "MEDIUM" + "severity": "MEDIUM", + "line": 7, + "fileName": "positive4.json" }, { - "line": 13, - "fileName": "positive5.json", "queryName": "MSK Cluster Logging Disabled", - "severity": "MEDIUM" + "severity": "MEDIUM", + "line": 13, + "fileName": "positive5.json" }, { - "line": 17, - "fileName": "positive5.json", "queryName": "MSK Cluster Logging Disabled", - "severity": "MEDIUM" + "severity": "MEDIUM", + "line": 17, + "fileName": "positive5.json" }, { + "queryName": "MSK Cluster Logging Disabled", + "severity": "MEDIUM", "line": 21, - "fileName": "positive5.json", + "fileName": "positive5.json" + }, + { "queryName": "MSK Cluster Logging Disabled", - "severity": "MEDIUM" + "severity": "MEDIUM", + "line": 13, + "fileName": "positive6.json" }, { + "queryName": "MSK Cluster Logging Disabled", + "severity": "MEDIUM", "line": 12, - "fileName": "positive3.yaml", + "fileName": "positive7.yaml" + }, + { "queryName": "MSK Cluster Logging Disabled", - "severity": "MEDIUM" + "severity": "MEDIUM", + "line": 15, + "fileName": "positive7.yaml" }, { - "line": 13, - "fileName": "positive6.json", "queryName": "MSK Cluster Logging Disabled", - "severity": "MEDIUM" + "severity": "MEDIUM", + "line": 18, + "fileName": "positive7.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/neptune_cluster_with_iam_database_authentication_disabled/query.rego b/assets/queries/cloudFormation/aws/neptune_cluster_with_iam_database_authentication_disabled/query.rego index ad3c8c0049a..2f3465301c9 100644 --- a/assets/queries/cloudFormation/aws/neptune_cluster_with_iam_database_authentication_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/neptune_cluster_with_iam_database_authentication_disabled/query.rego @@ -9,7 +9,7 @@ CxPolicy[result] { resource := Resources[name] resource.Type == "AWS::Neptune::DBCluster" properties := resource.Properties - properties.IamAuthEnabled == false + cf_lib.isCloudFormationFalse(properties.IamAuthEnabled) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/neptune_cluster_with_iam_database_authentication_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/neptune_cluster_with_iam_database_authentication_disabled/test/negative3.yaml new file mode 100644 index 00000000000..7f36c47ce9e --- /dev/null +++ b/assets/queries/cloudFormation/aws/neptune_cluster_with_iam_database_authentication_disabled/test/negative3.yaml @@ -0,0 +1,8 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: A sample template +Resources: + NeptuneDBCluster3: + Type: AWS::Neptune::DBCluster + Properties: + IamAuthEnabled: "true" + StorageEncrypted: "true" diff --git a/assets/queries/cloudFormation/aws/neptune_cluster_with_iam_database_authentication_disabled/test/positive3.yaml b/assets/queries/cloudFormation/aws/neptune_cluster_with_iam_database_authentication_disabled/test/positive3.yaml new file mode 100644 index 00000000000..dcc240c53e6 --- /dev/null +++ b/assets/queries/cloudFormation/aws/neptune_cluster_with_iam_database_authentication_disabled/test/positive3.yaml @@ -0,0 +1,13 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: A sample template +Resources: + NeptuneDBCluster: + Type: AWS::Neptune::DBCluster + Properties: + IamAuthEnabled: "false" + StorageEncrypted: "true" + NeptuneDBCluster2: + Type: AWS::Neptune::DBCluster + Properties: + IamAuthEnabled: "false" + StorageEncrypted: "true" diff --git a/assets/queries/cloudFormation/aws/neptune_cluster_with_iam_database_authentication_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/neptune_cluster_with_iam_database_authentication_disabled/test/positive_expected_result.json index d7aff56cde1..f51982aed87 100644 --- a/assets/queries/cloudFormation/aws/neptune_cluster_with_iam_database_authentication_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/neptune_cluster_with_iam_database_authentication_disabled/test/positive_expected_result.json @@ -1,26 +1,38 @@ [ { + "queryName": "Neptune Cluster With IAM Database Authentication Disabled", "severity": "HIGH", "line": 7, - "fileName": "positive1.yaml", - "queryName": "Neptune Cluster With IAM Database Authentication Disabled" + "fileName": "positive1.yaml" }, { + "queryName": "Neptune Cluster With IAM Database Authentication Disabled", "severity": "HIGH", "line": 12, - "fileName": "positive1.yaml", - "queryName": "Neptune Cluster With IAM Database Authentication Disabled" + "fileName": "positive1.yaml" }, { - "line": 8, - "fileName": "positive2.json", "queryName": "Neptune Cluster With IAM Database Authentication Disabled", - "severity": "HIGH" + "severity": "HIGH", + "line": 8, + "fileName": "positive2.json" }, { + "queryName": "Neptune Cluster With IAM Database Authentication Disabled", + "severity": "HIGH", "line": 15, - "fileName": "positive2.json", + "fileName": "positive2.json" + }, + { + "queryName": "Neptune Cluster With IAM Database Authentication Disabled", + "severity": "HIGH", + "line": 7, + "fileName": "positive3.yaml" + }, + { "queryName": "Neptune Cluster With IAM Database Authentication Disabled", - "severity": "HIGH" + "severity": "HIGH", + "line": 12, + "fileName": "positive3.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/neptune_database_cluster_encryption_disabled/query.rego b/assets/queries/cloudFormation/aws/neptune_database_cluster_encryption_disabled/query.rego index a17ecd1feff..4eff597c242 100644 --- a/assets/queries/cloudFormation/aws/neptune_database_cluster_encryption_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/neptune_database_cluster_encryption_disabled/query.rego @@ -9,7 +9,7 @@ CxPolicy[result] { resource := Resources[name] resource.Type == "AWS::Neptune::DBCluster" properties := resource.Properties - properties.StorageEncrypted == false + cf_lib.isCloudFormationFalse(properties.StorageEncrypted) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/neptune_database_cluster_encryption_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/neptune_database_cluster_encryption_disabled/test/negative3.yaml new file mode 100644 index 00000000000..35b188e8cd7 --- /dev/null +++ b/assets/queries/cloudFormation/aws/neptune_database_cluster_encryption_disabled/test/negative3.yaml @@ -0,0 +1,32 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: A sample template +Resources: + NeptuneDBCluster: + Type: AWS::Neptune::DBCluster + Properties: + AssociatedRoles: + - DBClusterRole + AvailabilityZones: + - String + DBClusterIdentifier: String + DBClusterParameterGroupName: String + DBSubnetGroupName: String + DeletionProtection: "true" + EnableCloudwatchLogsExports: + - String + EngineVersion: String + IamAuthEnabled: "true" + KmsKeyId: String + Port: 8182 + PreferredBackupWindow: String + PreferredMaintenanceWindow: String + RestoreToTime: String + RestoreType: String + SnapshotIdentifier: String + SourceDBClusterIdentifier: String + StorageEncrypted: "true" + Tags: + - Tag + UseLatestRestorableTime: "true" + VpcSecurityGroupIds: + - String diff --git a/assets/queries/cloudFormation/aws/neptune_database_cluster_encryption_disabled/test/positive3.yaml b/assets/queries/cloudFormation/aws/neptune_database_cluster_encryption_disabled/test/positive3.yaml new file mode 100644 index 00000000000..02a7efe7b3f --- /dev/null +++ b/assets/queries/cloudFormation/aws/neptune_database_cluster_encryption_disabled/test/positive3.yaml @@ -0,0 +1,32 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: A sample template +Resources: + NeptuneDBCluster: + Type: AWS::Neptune::DBCluster + Properties: + AssociatedRoles: + - DBClusterRole + AvailabilityZones: + - String + DBClusterIdentifier: String + DBClusterParameterGroupName: String + DBSubnetGroupName: String + DeletionProtection: "true" + EnableCloudwatchLogsExports: + - String + EngineVersion: String + IamAuthEnabled: "true" + KmsKeyId: String + Port: 8182 + PreferredBackupWindow: String + PreferredMaintenanceWindow: String + RestoreToTime: String + RestoreType: String + SnapshotIdentifier: String + SourceDBClusterIdentifier: String + StorageEncrypted: "false" + Tags: + - Tag + UseLatestRestorableTime: "true" + VpcSecurityGroupIds: + - String diff --git a/assets/queries/cloudFormation/aws/neptune_database_cluster_encryption_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/neptune_database_cluster_encryption_disabled/test/positive_expected_result.json index a489ef90893..56c1ab81ab8 100644 --- a/assets/queries/cloudFormation/aws/neptune_database_cluster_encryption_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/neptune_database_cluster_encryption_disabled/test/positive_expected_result.json @@ -1,14 +1,20 @@ [ { + "queryName": "Neptune Database Cluster Encryption Disabled", "severity": "HIGH", "line": 27, - "fileName": "positive1.yaml", - "queryName": "Neptune Database Cluster Encryption Disabled" + "fileName": "positive1.yaml" }, { + "queryName": "Neptune Database Cluster Encryption Disabled", + "severity": "HIGH", "line": 21, - "fileName": "positive2.json", + "fileName": "positive2.json" + }, + { "queryName": "Neptune Database Cluster Encryption Disabled", - "severity": "HIGH" + "severity": "HIGH", + "line": 27, + "fileName": "positive3.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/rds_db_instance_publicly_accessible/query.rego b/assets/queries/cloudFormation/aws/rds_db_instance_publicly_accessible/query.rego index 3dc8c986f01..5e257a878fe 100644 --- a/assets/queries/cloudFormation/aws/rds_db_instance_publicly_accessible/query.rego +++ b/assets/queries/cloudFormation/aws/rds_db_instance_publicly_accessible/query.rego @@ -8,7 +8,7 @@ CxPolicy[result] { [path, Resources] := walk(docs) resource := Resources[name] resource.Type == "AWS::RDS::DBInstance" - resource.Properties.PubliclyAccessible == true + cf_lib.isCloudFormationTrue(resource.Properties.PubliclyAccessible) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/rds_db_instance_publicly_accessible/test/negative3.yaml b/assets/queries/cloudFormation/aws/rds_db_instance_publicly_accessible/test/negative3.yaml new file mode 100644 index 00000000000..3e74abcf79a --- /dev/null +++ b/assets/queries/cloudFormation/aws/rds_db_instance_publicly_accessible/test/negative3.yaml @@ -0,0 +1,68 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: >- + Description": "AWS CloudFormation Sample Template for creating an Amazon RDS DB instance: + Sample template showing how to create a DB instance with Enhanced Monitoring enabled. + **WARNING** This template creates an RDS DB instance. You will be billed for the AWS + resources used if you create a stack from this template. +Parameters: + DBInstanceID: + Default: mydbinstance + Description: My database instance + Type: String + MinLength: '1' + MaxLength: '63' + AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*' + ConstraintDescription: >- + Must begin with a letter and must not end with a hyphen or contain two + consecutive hyphens. + DBName: + Default: mydb + Description: My database + Type: String + MinLength: '1' + MaxLength: '64' + AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*' + ConstraintDescription: Must begin with a letter and contain only alphanumeric characters. + DBInstanceClass: + Default: db.m5.large + Description: DB instance class + Type: String + ConstraintDescription: Must select a valid DB instance type. + DBAllocatedStorage: + Default: '50' + Description: The size of the database (GiB) + Type: Number + MinValue: '5' + MaxValue: '1024' + ConstraintDescription: must be between 20 and 65536 GiB. + DBUsername: + NoEcho: 'true' + Description: Username for MySQL database access + Type: String + MinLength: '1' + MaxLength: '16' + AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*' + ConstraintDescription: must begin with a letter and contain only alphanumeric characters. + DBPassword: + NoEcho: 'true' + Description: Password MySQL database access + Type: String + MinLength: '8' + MaxLength: '41' + AllowedPattern: '[a-zA-Z0-9]*' + ConstraintDescription: must contain only alphanumeric characters. +Resources: + MyDB: + Type: 'AWS::RDS::DBInstance' + Properties: + DBInstanceIdentifier: !Ref DBInstanceID + DBName: !Ref DBName + DBInstanceClass: !Ref DBInstanceClass + AllocatedStorage: !Ref DBAllocatedStorage + Engine: MySQL + EngineVersion: 8.0.16 + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + MonitoringInterval: '60' + MonitoringRoleArn: 'arn:aws:iam::123456789012:role/rds-monitoring-role' + PubliclyAccessible: 'false' diff --git a/assets/queries/cloudFormation/aws/rds_db_instance_publicly_accessible/test/positive3.yaml b/assets/queries/cloudFormation/aws/rds_db_instance_publicly_accessible/test/positive3.yaml new file mode 100644 index 00000000000..e401c86a551 --- /dev/null +++ b/assets/queries/cloudFormation/aws/rds_db_instance_publicly_accessible/test/positive3.yaml @@ -0,0 +1,69 @@ +#this is a problematic code where the query should report a result(s) +AWSTemplateFormatVersion: 2010-09-09 +Description: >- + Description": "AWS CloudFormation Sample Template for creating an Amazon RDS DB instance: + Sample template showing how to create a DB instance with Enhanced Monitoring enabled. + **WARNING** This template creates an RDS DB instance. You will be billed for the AWS + resources used if you create a stack from this template. +Parameters: + DBInstanceID: + Default: mydbinstance + Description: My database instance + Type: String + MinLength: '1' + MaxLength: '63' + AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*' + ConstraintDescription: >- + Must begin with a letter and must not end with a hyphen or contain two + consecutive hyphens. + DBName: + Default: mydb + Description: My database + Type: String + MinLength: '1' + MaxLength: '64' + AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*' + ConstraintDescription: Must begin with a letter and contain only alphanumeric characters. + DBInstanceClass: + Default: db.m5.large + Description: DB instance class + Type: String + ConstraintDescription: Must select a valid DB instance type. + DBAllocatedStorage: + Default: '50' + Description: The size of the database (GiB) + Type: Number + MinValue: '5' + MaxValue: '1024' + ConstraintDescription: must be between 20 and 65536 GiB. + DBUsername: + NoEcho: 'true' + Description: Username for MySQL database access + Type: String + MinLength: '1' + MaxLength: '16' + AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*' + ConstraintDescription: must begin with a letter and contain only alphanumeric characters. + DBPassword: + NoEcho: 'true' + Description: Password MySQL database access + Type: String + MinLength: '8' + MaxLength: '41' + AllowedPattern: '[a-zA-Z0-9]*' + ConstraintDescription: must contain only alphanumeric characters. +Resources: + MyDB: + Type: 'AWS::RDS::DBInstance' + Properties: + DBInstanceIdentifier: !Ref DBInstanceID + DBName: !Ref DBName + DBInstanceClass: !Ref DBInstanceClass + AllocatedStorage: !Ref DBAllocatedStorage + Engine: MySQL + EngineVersion: 8.0.16 + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + MonitoringInterval: '60' + MonitoringRoleArn: 'arn:aws:iam::123456789012:role/rds-monitoring-role' + PubliclyAccessible: "true" \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/rds_db_instance_publicly_accessible/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/rds_db_instance_publicly_accessible/test/positive_expected_result.json index 16573eb7012..8ab4a9e49bc 100644 --- a/assets/queries/cloudFormation/aws/rds_db_instance_publicly_accessible/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/rds_db_instance_publicly_accessible/test/positive_expected_result.json @@ -10,5 +10,11 @@ "severity": "CRITICAL", "line": 61, "fileName": "positive2.json" + }, + { + "queryName": "RDS DB Instance Publicly Accessible", + "severity": "CRITICAL", + "line": 69, + "fileName": "positive3.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/rds_db_instance_with_deletion_protection_disabled/query.rego b/assets/queries/cloudFormation/aws/rds_db_instance_with_deletion_protection_disabled/query.rego index 6a6f2ad99ce..8b204c39e3b 100644 --- a/assets/queries/cloudFormation/aws/rds_db_instance_with_deletion_protection_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/rds_db_instance_with_deletion_protection_disabled/query.rego @@ -9,7 +9,7 @@ CxPolicy[result] { resource := Resources[name] resource.Type == "AWS::RDS::DBInstance" properties := resource.Properties - properties.DeletionProtection == false + cf_lib.isCloudFormationFalse(properties.DeletionProtection) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/rds_db_instance_with_deletion_protection_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/rds_db_instance_with_deletion_protection_disabled/test/negative3.yaml new file mode 100644 index 00000000000..0d68fcd9abf --- /dev/null +++ b/assets/queries/cloudFormation/aws/rds_db_instance_with_deletion_protection_disabled/test/negative3.yaml @@ -0,0 +1,39 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: RDS Storage Encrypted +Parameters: + SourceDBInstanceIdentifier: + Type: String + DBInstanceType: + Type: String + SourceRegion: + Type: String +Resources: + MyKey: + Type: "AWS::KMS::Key" + Properties: + KeyPolicy: + Version: 2012-10-17 + Id: key-default-1 + Statement: + - Sid: Enable IAM User Permissions + Effect: Allow + Principal: + AWS: !Join + - "" + - - "arn:aws:iam::" + - !Ref "AWS::AccountId" + - ":root" + Action: "kms:*" + Resource: "*" + MyDBSmall: + Type: "AWS::RDS::DBInstance" + Properties: + DBInstanceClass: !Ref DBInstanceType + SourceDBInstanceIdentifier: !Ref SourceDBInstanceIdentifier + SourceRegion: !Ref SourceRegion + DeletionProtection: "true" + KmsKeyId: !Ref MyKey +Outputs: + InstanceId: + Description: InstanceId of the newly created RDS Instance + Value: !Ref MyDBSmall diff --git a/assets/queries/cloudFormation/aws/rds_db_instance_with_deletion_protection_disabled/test/positive5.yaml b/assets/queries/cloudFormation/aws/rds_db_instance_with_deletion_protection_disabled/test/positive5.yaml new file mode 100644 index 00000000000..7959c28f774 --- /dev/null +++ b/assets/queries/cloudFormation/aws/rds_db_instance_with_deletion_protection_disabled/test/positive5.yaml @@ -0,0 +1,40 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: RDS Storage Encrypted +Parameters: + SourceDBInstanceIdentifier: + Type: String + DBInstanceType: + Type: String + SourceRegion: + Type: String +Resources: + MyKey: + Type: "AWS::KMS::Key" + Properties: + KeyPolicy: + Version: 2012-10-17 + Id: key-default-1 + Statement: + - Sid: Enable IAM User Permissions + Effect: Allow + Principal: + AWS: !Join + - "" + - - "arn:aws:iam::" + - !Ref "AWS::AccountId" + - ":root" + Action: "kms:*" + Resource: "*" + MyDBSmall: + Type: "AWS::RDS::DBInstance" + Properties: + DBInstanceClass: !Ref DBInstanceType + SourceDBInstanceIdentifier: !Ref SourceDBInstanceIdentifier + SourceRegion: !Ref SourceRegion + DeletionProtection: "false" + KmsKeyId: !Ref MyKey +Outputs: + InstanceId: + Description: InstanceId of the newly created RDS Instance + Value: !Ref MyDBSmall + diff --git a/assets/queries/cloudFormation/aws/rds_db_instance_with_deletion_protection_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/rds_db_instance_with_deletion_protection_disabled/test/positive_expected_result.json index 481c07abf6c..af7ef58369f 100644 --- a/assets/queries/cloudFormation/aws/rds_db_instance_with_deletion_protection_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/rds_db_instance_with_deletion_protection_disabled/test/positive_expected_result.json @@ -18,9 +18,15 @@ "fileName": "positive3.json" }, { - "fileName": "positive4.json", "queryName": "RDS DB Instance With Deletion Protection Disabled", "severity": "LOW", - "line": 45 + "line": 45, + "fileName": "positive4.json" + }, + { + "queryName": "RDS DB Instance With Deletion Protection Disabled", + "severity": "LOW", + "line": 34, + "fileName": "positive5.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/rds_multi_az_deployment_disabled/query.rego b/assets/queries/cloudFormation/aws/rds_multi_az_deployment_disabled/query.rego index 142a0546b87..53260a99892 100644 --- a/assets/queries/cloudFormation/aws/rds_multi_az_deployment_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/rds_multi_az_deployment_disabled/query.rego @@ -9,7 +9,7 @@ CxPolicy[result] { resource := Resources[name] resource.Type == "AWS::RDS::DBInstance" properties := resource.Properties - properties.MultiAZ == false + cf_lib.isCloudFormationFalse(properties.MultiAZ) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/rds_multi_az_deployment_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/rds_multi_az_deployment_disabled/test/negative3.yaml new file mode 100644 index 00000000000..68aec994eaa --- /dev/null +++ b/assets/queries/cloudFormation/aws/rds_multi_az_deployment_disabled/test/negative3.yaml @@ -0,0 +1,194 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: "AWS CloudFormation Sample Template RDS_MySQL_With_Read_Replica: + Sample template showing how to create a highly-available, RDS DBInstance with + a read replica. **WARNING** This template creates an Amazon Relational + Database Service database instance and Amazon CloudWatch alarms. You will be + billed for the AWS resources used if you create a stack from this template." +Parameters: + DBName: + Default: MyDatabase + Description: The database name + Type: String + MinLength: "1" + MaxLength: "64" + AllowedPattern: "[a-zA-Z][a-zA-Z0-9]*" + ConstraintDescription: must begin with a letter and contain only alphanumeric characters. + DBUser: + NoEcho: "true" + Description: The database admin account username + Type: String + MinLength: "1" + MaxLength: "16" + AllowedPattern: "[a-zA-Z][a-zA-Z0-9]*" + ConstraintDescription: must begin with a letter and contain only alphanumeric characters. + DBPassword: + NoEcho: "true" + Description: The database admin account password + Type: String + MinLength: "1" + MaxLength: "41" + AllowedPattern: "[a-zA-Z0-9]+" + ConstraintDescription: must contain only alphanumeric characters. + DBAllocatedStorage: + Default: "5" + Description: The size of the database (Gb) + Type: Number + MinValue: "5" + MaxValue: "1024" + ConstraintDescription: must be between 5 and 1024Gb. + DBInstanceClass: + Description: The database instance type + Type: String + Default: db.t2.small + AllowedValues: + - db.t1.micro + - db.m1.small + - db.m1.medium + - db.m1.large + - db.m1.xlarge + - db.m2.xlarge + - db.m2.2xlarge + - db.m2.4xlarge + - db.m3.medium + - db.m3.large + - db.m3.xlarge + - db.m3.2xlarge + - db.m4.large + - db.m4.xlarge + - db.m4.2xlarge + - db.m4.4xlarge + - db.m4.10xlarge + - db.r3.large + - db.r3.xlarge + - db.r3.2xlarge + - db.r3.4xlarge + - db.r3.8xlarge + - db.m2.xlarge + - db.m2.2xlarge + - db.m2.4xlarge + - db.cr1.8xlarge + - db.t2.micro + - db.t2.small + - db.t2.medium + - db.t2.large + ConstraintDescription: must select a valid database instance type. + EC2SecurityGroup: + Description: The EC2 security group that contains instances that need access to + the database + Default: default + Type: String + AllowedPattern: "[a-zA-Z0-9\\-]+" + ConstraintDescription: must be a valid security group name. +Conditions: + Is-EC2-VPC: + Fn::Or: + - Fn::Equals: + - Ref: AWS::Region + - eu-central-1 + - Fn::Equals: + - Ref: AWS::Region + - cn-north-1 + Is-EC2-Classic: + Fn::Not: + - Condition: Is-EC2-VPC +Resources: + DBEC2SecurityGroup: + Type: AWS::EC2::SecurityGroup + Condition: Is-EC2-VPC + Properties: + GroupDescription: Open database for access + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 3306 + ToPort: 3306 + SourceSecurityGroupName: + Ref: EC2SecurityGroup + DBSecurityGroup: + Type: AWS::RDS::DBSecurityGroup + Condition: Is-EC2-Classic + Properties: + DBSecurityGroupIngress: + - EC2SecurityGroupName: + Ref: EC2SecurityGroup + GroupDescription: database access + MasterDB: + Type: AWS::RDS::DBInstance + Properties: + DBName: + Ref: DBName + AllocatedStorage: + Ref: DBAllocatedStorage + DBInstanceClass: + Ref: DBInstanceClass + Engine: MySQL + MasterUsername: + Ref: DBUser + MasterUserPassword: + Ref: DBPassword + MultiAZ: "true" + Tags: + - Key: Name + Value: Master Database + VPCSecurityGroups: + Fn::If: + - Is-EC2-VPC + - - Fn::GetAtt: + - DBEC2SecurityGroup + - GroupId + - Ref: AWS::NoValue + DBSecurityGroups: + Fn::If: + - Is-EC2-Classic + - - Ref: DBSecurityGroup + - Ref: AWS::NoValue + DeletionPolicy: Snapshot + UpdateReplacePolicy: Snapshot + ReplicaDB: + Type: AWS::RDS::DBInstance + Properties: + SourceDBInstanceIdentifier: + Ref: MasterDB + DBInstanceClass: + Ref: DBInstanceClass + MultiAZ: "true" + Tags: + - Key: Name + Value: Read Replica Database +Outputs: + EC2Platform: + Description: Platform in which this stack is deployed + Value: + Fn::If: + - Is-EC2-VPC + - EC2-VPC + - EC2-Classic + MasterJDBCConnectionString: + Description: JDBC connection string for the master database + Value: + Fn::Join: + - "" + - - jdbc:mysql:// + - Fn::GetAtt: + - MasterDB + - Endpoint.Address + - ":" + - Fn::GetAtt: + - MasterDB + - Endpoint.Port + - / + - Ref: DBName + ReplicaJDBCConnectionString: + Description: JDBC connection string for the replica database + Value: + Fn::Join: + - "" + - - jdbc:mysql:// + - Fn::GetAtt: + - ReplicaDB + - Endpoint.Address + - ":" + - Fn::GetAtt: + - ReplicaDB + - Endpoint.Port + - / + - Ref: DBName diff --git a/assets/queries/cloudFormation/aws/rds_multi_az_deployment_disabled/test/positive3.yaml b/assets/queries/cloudFormation/aws/rds_multi_az_deployment_disabled/test/positive3.yaml new file mode 100644 index 00000000000..140bd412673 --- /dev/null +++ b/assets/queries/cloudFormation/aws/rds_multi_az_deployment_disabled/test/positive3.yaml @@ -0,0 +1,183 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: "AWS CloudFormation Sample Template RDS_MySQL_With_Read_Replica: + Sample template showing how to create a highly-available, RDS DBInstance with + a read replica. **WARNING** This template creates an Amazon Relational + Database Service database instance and Amazon CloudWatch alarms. You will be + billed for the AWS resources used if you create a stack from this template." +Parameters: + DBName: + Default: MyDatabase + Description: The database name + Type: String + MinLength: "1" + MaxLength: "64" + AllowedPattern: "[a-zA-Z][a-zA-Z0-9]*" + ConstraintDescription: must begin with a letter and contain only alphanumeric characters. + DBUser: + NoEcho: "true" + Description: The database admin account username + Type: String + MinLength: "1" + MaxLength: "16" + AllowedPattern: "[a-zA-Z][a-zA-Z0-9]*" + ConstraintDescription: must begin with a letter and contain only alphanumeric characters. + DBPassword: + NoEcho: "true" + Description: The database admin account password + Type: String + MinLength: "1" + MaxLength: "41" + AllowedPattern: "[a-zA-Z0-9]+" + ConstraintDescription: must contain only alphanumeric characters. + DBAllocatedStorage: + Default: "5" + Description: The size of the database (Gb) + Type: Number + MinValue: "5" + MaxValue: "1024" + ConstraintDescription: must be between 5 and 1024Gb. + DBInstanceClass: + Description: The database instance type + Type: String + Default: db.t2.small + AllowedValues: + - db.t1.micro + - db.m1.small + - db.m1.medium + - db.m1.large + - db.m1.xlarge + - db.m2.xlarge + - db.m2.2xlarge + - db.m2.4xlarge + - db.m3.medium + - db.m3.large + - db.m3.xlarge + - db.m3.2xlarge + - db.m4.large + - db.m4.xlarge + - db.m4.2xlarge + - db.m4.4xlarge + - db.m4.10xlarge + - db.r3.large + - db.r3.xlarge + - db.r3.2xlarge + - db.r3.4xlarge + - db.r3.8xlarge + - db.m2.xlarge + - db.m2.2xlarge + - db.m2.4xlarge + - db.cr1.8xlarge + - db.t2.micro + - db.t2.small + - db.t2.medium + - db.t2.large + ConstraintDescription: must select a valid database instance type. + EC2SecurityGroup: + Description: The EC2 security group that contains instances that need access to + the database + Default: default + Type: String + AllowedPattern: "[a-zA-Z0-9\\-]+" + ConstraintDescription: must be a valid security group name. +Conditions: + Is-EC2-VPC: + Fn::Or: + - Fn::Equals: + - Ref: AWS::Region + - eu-central-1 + - Fn::Equals: + - Ref: AWS::Region + - cn-north-1 + Is-EC2-Classic: + Fn::Not: + - Condition: Is-EC2-VPC +Resources: + DBEC2SecurityGroup: + Type: AWS::EC2::SecurityGroup + Condition: Is-EC2-VPC + Properties: + GroupDescription: Open database for access + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 3306 + ToPort: 3306 + SourceSecurityGroupName: + Ref: EC2SecurityGroup + DBSecurityGroup: + Type: AWS::RDS::DBSecurityGroup + Condition: Is-EC2-Classic + Properties: + DBSecurityGroupIngress: + - EC2SecurityGroupName: + Ref: EC2SecurityGroup + GroupDescription: database access + MasterDB: + Type: AWS::RDS::DBInstance + Properties: + DBName: + Ref: DBName + AllocatedStorage: + Ref: DBAllocatedStorage + DBInstanceClass: + Ref: DBInstanceClass + Engine: MySQL + MasterUsername: + Ref: DBUser + MasterUserPassword: + Ref: DBPassword + MultiAZ: "false" + Tags: + - Key: Name + Value: Master Database + VPCSecurityGroups: + Fn::If: + - Is-EC2-VPC + - - Fn::GetAtt: + - DBEC2SecurityGroup + - GroupId + - Ref: AWS::NoValue + DBSecurityGroups: + Fn::If: + - Is-EC2-Classic + - - Ref: DBSecurityGroup + - Ref: AWS::NoValue + DeletionPolicy: Snapshot + UpdateReplacePolicy: Snapshot +Outputs: + EC2Platform: + Description: Platform in which this stack is deployed + Value: + Fn::If: + - Is-EC2-VPC + - EC2-VPC + - EC2-Classic + MasterJDBCConnectionString: + Description: JDBC connection string for the master database + Value: + Fn::Join: + - "" + - - jdbc:mysql:// + - Fn::GetAtt: + - MasterDB + - Endpoint.Address + - ":" + - Fn::GetAtt: + - MasterDB + - Endpoint.Port + - / + - Ref: DBName + ReplicaJDBCConnectionString: + Description: JDBC connection string for the replica database + Value: + Fn::Join: + - "" + - - jdbc:mysql:// + - Fn::GetAtt: + - ReplicaDB + - Endpoint.Address + - ":" + - Fn::GetAtt: + - ReplicaDB + - Endpoint.Port + - / + - Ref: DBName diff --git a/assets/queries/cloudFormation/aws/rds_multi_az_deployment_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/rds_multi_az_deployment_disabled/test/positive_expected_result.json index 220a107973c..4787fe06159 100644 --- a/assets/queries/cloudFormation/aws/rds_multi_az_deployment_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/rds_multi_az_deployment_disabled/test/positive_expected_result.json @@ -22,5 +22,11 @@ "fileName": "positive2.json", "queryName": "RDS Multi-AZ Deployment Disabled", "severity": "MEDIUM" + }, + { + "queryName": "RDS Multi-AZ Deployment Disabled", + "severity": "MEDIUM", + "line": 128, + "fileName": "positive3.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/rds_storage_encryption_disabled/query.rego b/assets/queries/cloudFormation/aws/rds_storage_encryption_disabled/query.rego index 3ad76718cd0..06b7dbaf66f 100644 --- a/assets/queries/cloudFormation/aws/rds_storage_encryption_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/rds_storage_encryption_disabled/query.rego @@ -8,7 +8,7 @@ CxPolicy[result] { [path, Resources] := walk(docs) resource := Resources[name] resource.Type == "AWS::RDS::DBCluster" - resource.Properties.StorageEncrypted == false + cf_lib.isCloudFormationFalse(resource.Properties.StorageEncrypted) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/rds_storage_encryption_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/rds_storage_encryption_disabled/test/negative3.yaml new file mode 100644 index 00000000000..da332cb0b3b --- /dev/null +++ b/assets/queries/cloudFormation/aws/rds_storage_encryption_disabled/test/negative3.yaml @@ -0,0 +1,53 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: Creates RDS Cluster +Resources: + RDSCluster: + Properties: + DBClusterParameterGroupName: + Ref: RDSDBClusterParameterGroup + DBSubnetGroupName: DBSubnetGroup + Engine: aurora + MasterUserPassword: password + MasterUsername: username + StorageEncrypted: "true" + Type: "AWS::RDS::DBCluster" + RDSDBClusterParameterGroup: + Properties: + Description: "CloudFormation Sample Aurora Cluster Parameter Group" + Family: aurora5.6 + Parameters: + time_zone: US/Eastern + Type: "AWS::RDS::DBClusterParameterGroup" + RDSDBInstance1: + Properties: + AvailabilityZone: eu-west-1b + DBClusterIdentifier: + Ref: RDSCluster + DBInstanceClass: db.r3.xlarge + DBParameterGroupName: + Ref: RDSDBParameterGroup + DBSubnetGroupName: DBSubnetGroup + Engine: aurora + PubliclyAccessible: "true" + Type: "AWS::RDS::DBInstance" + RDSDBInstance2: + Properties: + AvailabilityZone: eu-west-1b + DBClusterIdentifier: + Ref: RDSCluster + DBInstanceClass: db.r3.xlarge + DBParameterGroupName: + Ref: RDSDBParameterGroup + DBSubnetGroupName: DBSubnetGroup + Engine: aurora + PubliclyAccessible: "true" + Type: "AWS::RDS::DBInstance" + RDSDBParameterGroup: + Type: 'AWS::RDS::DBParameterGroup' + Properties: + Description: CloudFormation Sample Aurora Parameter Group + Family: aurora5.6 + Parameters: + sql_mode: IGNORE_SPACE + max_allowed_packet: 1024 + innodb_buffer_pool_size: '{DBInstanceClassMemory*3/4}' diff --git a/assets/queries/cloudFormation/aws/rds_storage_encryption_disabled/test/positive6.yaml b/assets/queries/cloudFormation/aws/rds_storage_encryption_disabled/test/positive6.yaml new file mode 100644 index 00000000000..97e112a6916 --- /dev/null +++ b/assets/queries/cloudFormation/aws/rds_storage_encryption_disabled/test/positive6.yaml @@ -0,0 +1,54 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: Creates RDS Cluster +Resources: + RDSCluster: + Properties: + DBClusterParameterGroupName: + Ref: RDSDBClusterParameterGroup + DBSubnetGroupName: DBSubnetGroup + Engine: aurora + MasterUserPassword: password + MasterUsername: username + StorageEncrypted: "false" + Type: "AWS::RDS::DBCluster" + RDSDBClusterParameterGroup: + Properties: + Description: "CloudFormation Sample Aurora Cluster Parameter Group" + Family: aurora5.6 + Parameters: + time_zone: US/Eastern + Type: "AWS::RDS::DBClusterParameterGroup" + RDSDBInstance1: + Properties: + AvailabilityZone: eu-west-1b + DBClusterIdentifier: + Ref: RDSCluster + DBInstanceClass: db.r3.xlarge + DBParameterGroupName: + Ref: RDSDBParameterGroup + DBSubnetGroupName: DBSubnetGroup + Engine: aurora + PubliclyAccessible: "true" + Type: "AWS::RDS::DBInstance" + RDSDBInstance2: + Properties: + AvailabilityZone: eu-west-1b + DBClusterIdentifier: + Ref: RDSCluster + DBInstanceClass: db.r3.xlarge + DBParameterGroupName: + Ref: RDSDBParameterGroup + DBSubnetGroupName: DBSubnetGroup + Engine: aurora + PubliclyAccessible: "true" + Type: "AWS::RDS::DBInstance" + RDSDBParameterGroup: + Type: 'AWS::RDS::DBParameterGroup' + Properties: + Description: CloudFormation Sample Aurora Parameter Group + Family: aurora5.6 + Parameters: + sql_mode: IGNORE_SPACE + max_allowed_packet: 1024 + innodb_buffer_pool_size: '{DBInstanceClassMemory*3/4}' + diff --git a/assets/queries/cloudFormation/aws/rds_storage_encryption_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/rds_storage_encryption_disabled/test/positive_expected_result.json index 595b5a6a0b1..b91a1a46a5a 100644 --- a/assets/queries/cloudFormation/aws/rds_storage_encryption_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/rds_storage_encryption_disabled/test/positive_expected_result.json @@ -18,15 +18,21 @@ "fileName": "positive3.json" }, { - "fileName": "positive4.json", "queryName": "RDS Storage Encryption Disabled", "severity": "HIGH", - "line": 59 + "line": 59, + "fileName": "positive4.json" }, { - "fileName": "positive5.yaml", "queryName": "RDS Storage Encryption Disabled", "severity": "HIGH", - "line": 5 + "line": 5, + "fileName": "positive5.yaml" + }, + { + "queryName": "RDS Storage Encryption Disabled", + "severity": "HIGH", + "line": 12, + "fileName": "positive6.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/rds_storage_not_encrypted/query.rego b/assets/queries/cloudFormation/aws/rds_storage_not_encrypted/query.rego index 837fb6ec5bf..bf7608bee48 100644 --- a/assets/queries/cloudFormation/aws/rds_storage_not_encrypted/query.rego +++ b/assets/queries/cloudFormation/aws/rds_storage_not_encrypted/query.rego @@ -29,8 +29,8 @@ CxPolicy[result] { resource.Type == "AWS::RDS::DBInstance" properties := resource.Properties - - properties.StorageEncrypted == false + + cf_lib.isCloudFormationFalse(properties.StorageEncrypted) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/rds_storage_not_encrypted/test/negative3.yaml b/assets/queries/cloudFormation/aws/rds_storage_not_encrypted/test/negative3.yaml new file mode 100644 index 00000000000..6401b1c3c05 --- /dev/null +++ b/assets/queries/cloudFormation/aws/rds_storage_not_encrypted/test/negative3.yaml @@ -0,0 +1,35 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: RDS Storage Encrypted +Parameters: + SourceDBInstanceIdentifier: + Type: String + DBInstanceType: + Type: String + SourceRegion: + Type: String +Resources: + MyKey: + Type: "AWS::KMS::Key" + Properties: + KeyPolicy: + Version: 2012-10-17 + Id: key-default-1 + Statement: + - Sid: Enable IAM User Permissions + Effect: Allow + Principal: + AWS: !Join + - "" + - - "arn:aws:iam::" + - !Ref "AWS::AccountId" + - ":root" + Action: "kms:*" + Resource: "*" + MyDBSmall: + Type: "AWS::RDS::DBInstance" + Properties: + DBInstanceClass: !Ref DBInstanceType + SourceDBInstanceIdentifier: !Ref SourceDBInstanceIdentifier + SourceRegion: !Ref SourceRegion + KmsKeyId: !Ref MyKey + StorageEncrypted: "true" \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/rds_storage_not_encrypted/test/positive5.yaml b/assets/queries/cloudFormation/aws/rds_storage_not_encrypted/test/positive5.yaml new file mode 100644 index 00000000000..f35e95c40b8 --- /dev/null +++ b/assets/queries/cloudFormation/aws/rds_storage_not_encrypted/test/positive5.yaml @@ -0,0 +1,37 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: RDS Storage Encrypted +Parameters: + SourceDBInstanceIdentifier: + Type: String + DBInstanceType: + Type: String + SourceRegion: + Type: String +Resources: + MyKey: + Type: "AWS::KMS::Key" + Properties: + KeyPolicy: + Version: 2012-10-17 + Id: key-default-1 + Statement: + - Sid: Enable IAM User Permissions + Effect: Allow + Principal: + AWS: !Join + - "" + - - "arn:aws:iam::" + - !Ref "AWS::AccountId" + - ":root" + Action: "kms:*" + Resource: "*" + MyDBSmall: + Type: "AWS::RDS::DBInstance" + Properties: + DBInstanceClass: !Ref DBInstanceType + SourceDBInstanceIdentifier: !Ref SourceDBInstanceIdentifier + SourceRegion: !Ref SourceRegion + KmsKeyId: !Ref MyKey + StorageEncrypted: "false" + + diff --git a/assets/queries/cloudFormation/aws/rds_storage_not_encrypted/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/rds_storage_not_encrypted/test/positive_expected_result.json index 1cde5405887..163b2c257f4 100644 --- a/assets/queries/cloudFormation/aws/rds_storage_not_encrypted/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/rds_storage_not_encrypted/test/positive_expected_result.json @@ -1,15 +1,15 @@ [ { + "queryName": "RDS Storage Not Encrypted", "severity": "HIGH", - "line": 30, - "fileName": "positive2.yaml", - "queryName": "RDS Storage Not Encrypted" + "line": 35, + "fileName": "positive1.yaml" }, { "queryName": "RDS Storage Not Encrypted", "severity": "HIGH", - "line": 35, - "fileName": "positive1.yaml" + "line": 30, + "fileName": "positive2.yaml" }, { "queryName": "RDS Storage Not Encrypted", @@ -22,5 +22,11 @@ "severity": "HIGH", "line": 45, "fileName": "positive4.json" + }, + { + "queryName": "RDS Storage Not Encrypted", + "severity": "HIGH", + "line": 35, + "fileName": "positive5.json" } ] diff --git a/assets/queries/cloudFormation/aws/redshift_not_encrypted/query.rego b/assets/queries/cloudFormation/aws/redshift_not_encrypted/query.rego index 183b4fb9931..a9f518679c9 100644 --- a/assets/queries/cloudFormation/aws/redshift_not_encrypted/query.rego +++ b/assets/queries/cloudFormation/aws/redshift_not_encrypted/query.rego @@ -26,7 +26,7 @@ CxPolicy[result] { properties := resource.Properties - properties.Encrypted == false + cf_lib.isCloudFormationFalse(properties.Encrypted) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/redshift_not_encrypted/test/negative3.yaml b/assets/queries/cloudFormation/aws/redshift_not_encrypted/test/negative3.yaml new file mode 100644 index 00000000000..6e312a9a67b --- /dev/null +++ b/assets/queries/cloudFormation/aws/redshift_not_encrypted/test/negative3.yaml @@ -0,0 +1,25 @@ +AWSTemplateFormatVersion: 2010-09-11 +Description: Redshift Stack2 +Resources: + RedshiftCluster2: + Type: AWS::Redshift::Cluster + Properties: + ClusterSubnetGroupName: !Ref RedshiftClusterSubnetGroup + ClusterType: !If [ SingleNode, single-node, multi-node ] + NumberOfNodes: !If [ SingleNode, !Ref 'AWS::NoValue', !Ref RedshiftNodeCount ] #' + DBName: !Sub ${DatabaseName} + IamRoles: + - !GetAtt RawDataBucketAccessRole.Arn + MasterUserPassword: !Ref MasterUserPassword + MasterUsername: !Ref MasterUsername + PubliclyAccessible: "true" + NodeType: dc1.large + Port: 5439 + VpcSecurityGroupIds: + - !Sub ${RedshiftSecurityGroup} + PreferredMaintenanceWindow: Sun:09:15-Sun:09:45 + Encrypted: "true" + DataBucket: + Type: AWS::S3::Bucket + Properties: + BucketName: !Sub ${DataBucketName} diff --git a/assets/queries/cloudFormation/aws/redshift_not_encrypted/test/positive5.yaml b/assets/queries/cloudFormation/aws/redshift_not_encrypted/test/positive5.yaml new file mode 100644 index 00000000000..9981695ad8b --- /dev/null +++ b/assets/queries/cloudFormation/aws/redshift_not_encrypted/test/positive5.yaml @@ -0,0 +1,26 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: Redshift Stack +Resources: + RedshiftCluster: + Type: AWS::Redshift::Cluster + Properties: + ClusterSubnetGroupName: !Ref RedshiftClusterSubnetGroup + ClusterType: !If [ SingleNode, single-node, multi-node ] + NumberOfNodes: !If [ SingleNode, !Ref 'AWS::NoValue', !Ref RedshiftNodeCount ] #' + DBName: !Sub ${DatabaseName} + IamRoles: + - !GetAtt RawDataBucketAccessRole.Arn + MasterUserPassword: !Ref MasterUserPassword + MasterUsername: !Ref MasterUsername + PubliclyAccessible: "true" + NodeType: dc1.large + Port: 5439 + VpcSecurityGroupIds: + - !Sub ${RedshiftSecurityGroup} + PreferredMaintenanceWindow: Sun:09:15-Sun:09:45 + DataBucket: + Type: AWS::S3::Bucket + Properties: + BucketName: !Sub ${DataBucketName} + + diff --git a/assets/queries/cloudFormation/aws/redshift_not_encrypted/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/redshift_not_encrypted/test/positive_expected_result.json index 157fea11bac..8c7b0132cf5 100644 --- a/assets/queries/cloudFormation/aws/redshift_not_encrypted/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/redshift_not_encrypted/test/positive_expected_result.json @@ -22,5 +22,11 @@ "severity": "HIGH", "line": 32, "fileName": "positive4.json" + }, + { + "queryName": "Redshift Not Encrypted", + "severity": "HIGH", + "line": 6, + "fileName": "positive5.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/redshift_publicly_accessible/query.rego b/assets/queries/cloudFormation/aws/redshift_publicly_accessible/query.rego index 4a87946f364..abc8e827abe 100644 --- a/assets/queries/cloudFormation/aws/redshift_publicly_accessible/query.rego +++ b/assets/queries/cloudFormation/aws/redshift_publicly_accessible/query.rego @@ -22,7 +22,7 @@ CxPolicy[result] { CxPolicy[result] { resource := input.document[i].Resources[name] resource.Type == "AWS::Redshift::Cluster" - resource.Properties.PubliclyAccessible == true + cf_lib.isCloudFormationTrue(resource.Properties.PubliclyAccessible) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/redshift_publicly_accessible/test/negative3.yaml b/assets/queries/cloudFormation/aws/redshift_publicly_accessible/test/negative3.yaml new file mode 100644 index 00000000000..9a3d4ed6672 --- /dev/null +++ b/assets/queries/cloudFormation/aws/redshift_publicly_accessible/test/negative3.yaml @@ -0,0 +1,15 @@ +#this code is a correct code for which the query should not find any result +Resources: + myCluster: + Type: "AWS::Redshift::Cluster" + Properties: + PubliclyAccessible: "false" + DBName: "mydb" + MasterUsername: "master" + MasterUserPassword: + Ref: "MasterUserPassword" + NodeType: "ds2.xlarge" + ClusterType: "single-node" + Tags: + - Key: foo + Value: bar diff --git a/assets/queries/cloudFormation/aws/redshift_publicly_accessible/test/positive3.yaml b/assets/queries/cloudFormation/aws/redshift_publicly_accessible/test/positive3.yaml new file mode 100644 index 00000000000..388155d1635 --- /dev/null +++ b/assets/queries/cloudFormation/aws/redshift_publicly_accessible/test/positive3.yaml @@ -0,0 +1,26 @@ +Resources: + myCluster: + Type: "AWS::Redshift::Cluster" + Properties: + DBName: "mydb" + MasterUsername: "master" + MasterUserPassword: + Ref: "MasterUserPassword" + NodeType: "ds2.xlarge" + ClusterType: "single-node" + Tags: + - Key: foo + Value: bar + myCluster2: + Type: "AWS::Redshift::Cluster" + Properties: + PubliclyAccessible: "true" + DBName: "mydb" + MasterUsername: "master" + MasterUserPassword: + Ref: "MasterUserPassword" + NodeType: "ds2.xlarge" + ClusterType: "single-node" + Tags: + - Key: foo + Value: bar diff --git a/assets/queries/cloudFormation/aws/redshift_publicly_accessible/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/redshift_publicly_accessible/test/positive_expected_result.json index 6af346d4fbe..96ef86a560f 100644 --- a/assets/queries/cloudFormation/aws/redshift_publicly_accessible/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/redshift_publicly_accessible/test/positive_expected_result.json @@ -22,5 +22,17 @@ "severity": "MEDIUM", "line": 30, "fileName": "positive2.json" + }, + { + "queryName": "Redshift Publicly Accessible", + "severity": "MEDIUM", + "line": 4, + "fileName": "positive3.yaml" + }, + { + "queryName": "Redshift Publicly Accessible", + "severity": "MEDIUM", + "line": 17, + "fileName": "positive3.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/s3_bucket_allows_public_acl/query.rego b/assets/queries/cloudFormation/aws/s3_bucket_allows_public_acl/query.rego index ff17c199019..ef838adafae 100644 --- a/assets/queries/cloudFormation/aws/s3_bucket_allows_public_acl/query.rego +++ b/assets/queries/cloudFormation/aws/s3_bucket_allows_public_acl/query.rego @@ -46,7 +46,7 @@ CxPolicy[result] { resource.Type == "AWS::S3::Bucket" PublicAccessBlockConfiguration := resource.Properties.PublicAccessBlockConfiguration - PublicAccessBlockConfiguration.BlockPublicAcls == false + cf_lib.isCloudFormationFalse(PublicAccessBlockConfiguration.BlockPublicAcls) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/s3_bucket_allows_public_acl/test/negative3.yaml b/assets/queries/cloudFormation/aws/s3_bucket_allows_public_acl/test/negative3.yaml new file mode 100644 index 00000000000..40d16c7688f --- /dev/null +++ b/assets/queries/cloudFormation/aws/s3_bucket_allows_public_acl/test/negative3.yaml @@ -0,0 +1,9 @@ +Resources: + Bucket1: + Type: AWS::S3::Bucket + Properties: + PublicAccessBlockConfiguration: + BlockPublicAcls : "true" + BlockPublicPolicy : "true" + IgnorePublicAcls : "true" + RestrictPublicBuckets : "true" \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/s3_bucket_allows_public_acl/test/positive3.yaml b/assets/queries/cloudFormation/aws/s3_bucket_allows_public_acl/test/positive3.yaml new file mode 100644 index 00000000000..a6f81a6c95b --- /dev/null +++ b/assets/queries/cloudFormation/aws/s3_bucket_allows_public_acl/test/positive3.yaml @@ -0,0 +1,23 @@ +Resources: + Bucket11: + Type: AWS::S3::Bucket + Properties: +--- +Resources: + Bucket12: + Type: AWS::S3::Bucket + Properties: + PublicAccessBlockConfiguration: + BlockPublicPolicy : "true" + IgnorePublicAcls : "true" + RestrictPublicBuckets : "true" +--- +Resources: + Bucket13: + Type: AWS::S3::Bucket + Properties: + PublicAccessBlockConfiguration: + BlockPublicAcls: "false" + BlockPublicPolicy : "true" + IgnorePublicAcls : "true" + RestrictPublicBuckets : "true" diff --git a/assets/queries/cloudFormation/aws/s3_bucket_allows_public_acl/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/s3_bucket_allows_public_acl/test/positive_expected_result.json index f61b002664e..b40c557aff1 100644 --- a/assets/queries/cloudFormation/aws/s3_bucket_allows_public_acl/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/s3_bucket_allows_public_acl/test/positive_expected_result.json @@ -22,5 +22,23 @@ "severity": "MEDIUM", "line": 7, "filename": "positive2.json" + }, + { + "queryName": "S3 Bucket Allows Public ACL", + "severity": "MEDIUM", + "line": 4, + "filename": "positive3.yaml" + }, + { + "queryName": "S3 Bucket Allows Public ACL", + "severity": "MEDIUM", + "line": 10, + "filename": "positive3.yaml" + }, + { + "queryName": "S3 Bucket Allows Public ACL", + "severity": "MEDIUM", + "line": 20, + "filename": "positive3.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/s3_bucket_with_public_policy/query.rego b/assets/queries/cloudFormation/aws/s3_bucket_with_public_policy/query.rego index 5e168f28eec..22472633538 100644 --- a/assets/queries/cloudFormation/aws/s3_bucket_with_public_policy/query.rego +++ b/assets/queries/cloudFormation/aws/s3_bucket_with_public_policy/query.rego @@ -46,7 +46,7 @@ CxPolicy[result] { resource.Type == "AWS::S3::Bucket" PublicAccessBlockConfiguration := resource.Properties.PublicAccessBlockConfiguration - PublicAccessBlockConfiguration.BlockPublicPolicy == false + cf_lib.isCloudFormationFalse(PublicAccessBlockConfiguration.BlockPublicPolicy) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/s3_bucket_with_public_policy/test/negative1.yaml b/assets/queries/cloudFormation/aws/s3_bucket_with_public_policy/test/negative1.yaml index 24575acaf85..40d16c7688f 100644 --- a/assets/queries/cloudFormation/aws/s3_bucket_with_public_policy/test/negative1.yaml +++ b/assets/queries/cloudFormation/aws/s3_bucket_with_public_policy/test/negative1.yaml @@ -3,7 +3,7 @@ Resources: Type: AWS::S3::Bucket Properties: PublicAccessBlockConfiguration: - BlockPublicAcls : true - BlockPublicPolicy : true - IgnorePublicAcls : true - RestrictPublicBuckets : true \ No newline at end of file + BlockPublicAcls : "true" + BlockPublicPolicy : "true" + IgnorePublicAcls : "true" + RestrictPublicBuckets : "true" \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/s3_bucket_with_public_policy/test/negative3.yaml b/assets/queries/cloudFormation/aws/s3_bucket_with_public_policy/test/negative3.yaml new file mode 100644 index 00000000000..24575acaf85 --- /dev/null +++ b/assets/queries/cloudFormation/aws/s3_bucket_with_public_policy/test/negative3.yaml @@ -0,0 +1,9 @@ +Resources: + Bucket1: + Type: AWS::S3::Bucket + Properties: + PublicAccessBlockConfiguration: + BlockPublicAcls : true + BlockPublicPolicy : true + IgnorePublicAcls : true + RestrictPublicBuckets : true \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/s3_bucket_with_public_policy/test/positive3.yaml b/assets/queries/cloudFormation/aws/s3_bucket_with_public_policy/test/positive3.yaml new file mode 100644 index 00000000000..e56b9978d81 --- /dev/null +++ b/assets/queries/cloudFormation/aws/s3_bucket_with_public_policy/test/positive3.yaml @@ -0,0 +1,21 @@ +Resources: + Bucket11: + Type: AWS::S3::Bucket + Properties: +--- +Resources: + Bucket12: + Type: AWS::S3::Bucket + Properties: + PublicAccessBlockConfiguration: + RestrictPublicBuckets : "true" +--- +Resources: + Bucket13: + Type: AWS::S3::Bucket + Properties: + PublicAccessBlockConfiguration: + BlockPublicAcls: "false" + BlockPublicPolicy : "false" + IgnorePublicAcls : "false" + RestrictPublicBuckets : "true" diff --git a/assets/queries/cloudFormation/aws/s3_bucket_with_public_policy/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/s3_bucket_with_public_policy/test/positive_expected_result.json index 4c6fc03d730..c72d95ef9a2 100755 --- a/assets/queries/cloudFormation/aws/s3_bucket_with_public_policy/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/s3_bucket_with_public_policy/test/positive_expected_result.json @@ -22,5 +22,23 @@ "severity": "HIGH", "line": 8, "filename": "positive2.json" + }, + { + "queryName": "S3 Bucket Allows Public Policy", + "severity": "HIGH", + "line": 4, + "filename": "positive3.yaml" + }, + { + "queryName": "S3 Bucket Allows Public Policy", + "severity": "HIGH", + "line": 10, + "filename": "positive3.yaml" + }, + { + "queryName": "S3 Bucket Allows Public Policy", + "severity": "HIGH", + "line": 19, + "filename": "positive3.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/s3_bucket_without_ignore_public_acl/query.rego b/assets/queries/cloudFormation/aws/s3_bucket_without_ignore_public_acl/query.rego index aa3510e8f5d..e04775aefc2 100644 --- a/assets/queries/cloudFormation/aws/s3_bucket_without_ignore_public_acl/query.rego +++ b/assets/queries/cloudFormation/aws/s3_bucket_without_ignore_public_acl/query.rego @@ -46,7 +46,7 @@ CxPolicy[result] { resource.Type == "AWS::S3::Bucket" PublicAccessBlockConfiguration := resource.Properties.PublicAccessBlockConfiguration - PublicAccessBlockConfiguration.IgnorePublicAcls == false + cf_lib.isCloudFormationFalse(PublicAccessBlockConfiguration.IgnorePublicAcls) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/s3_bucket_without_ignore_public_acl/test/negative3.yaml b/assets/queries/cloudFormation/aws/s3_bucket_without_ignore_public_acl/test/negative3.yaml new file mode 100644 index 00000000000..40d16c7688f --- /dev/null +++ b/assets/queries/cloudFormation/aws/s3_bucket_without_ignore_public_acl/test/negative3.yaml @@ -0,0 +1,9 @@ +Resources: + Bucket1: + Type: AWS::S3::Bucket + Properties: + PublicAccessBlockConfiguration: + BlockPublicAcls : "true" + BlockPublicPolicy : "true" + IgnorePublicAcls : "true" + RestrictPublicBuckets : "true" \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/s3_bucket_without_ignore_public_acl/test/positive3.yaml b/assets/queries/cloudFormation/aws/s3_bucket_without_ignore_public_acl/test/positive3.yaml new file mode 100644 index 00000000000..b92dc78d2b7 --- /dev/null +++ b/assets/queries/cloudFormation/aws/s3_bucket_without_ignore_public_acl/test/positive3.yaml @@ -0,0 +1,22 @@ +Resources: + Bucket11: + Type: AWS::S3::Bucket + Properties: +--- +Resources: + Bucket12: + Type: AWS::S3::Bucket + Properties: + PublicAccessBlockConfiguration: + BlockPublicPolicy : "true" + RestrictPublicBuckets : "true" +--- +Resources: + Bucket13: + Type: AWS::S3::Bucket + Properties: + PublicAccessBlockConfiguration: + BlockPublicAcls: "false" + BlockPublicPolicy : "true" + IgnorePublicAcls : "false" + RestrictPublicBuckets : "true" diff --git a/assets/queries/cloudFormation/aws/s3_bucket_without_ignore_public_acl/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/s3_bucket_without_ignore_public_acl/test/positive_expected_result.json index 69cfe9bac7c..aac17c770d3 100755 --- a/assets/queries/cloudFormation/aws/s3_bucket_without_ignore_public_acl/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/s3_bucket_without_ignore_public_acl/test/positive_expected_result.json @@ -22,5 +22,23 @@ "severity": "MEDIUM", "line": 9, "filename": "positive2.json" + }, + { + "queryName": "S3 Bucket Without Ignore Public ACL", + "severity": "MEDIUM", + "line": 4, + "filename": "positive3.yaml" + }, + { + "queryName": "S3 Bucket Without Ignore Public ACL", + "severity": "MEDIUM", + "line": 10, + "filename": "positive3.yaml" + }, + { + "queryName": "S3 Bucket Without Ignore Public ACL", + "severity": "MEDIUM", + "line": 21, + "filename": "positive3.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/s3_bucket_without_restriction_of_public_bucket/query.rego b/assets/queries/cloudFormation/aws/s3_bucket_without_restriction_of_public_bucket/query.rego index 45fabc84cff..3d0afe851f1 100644 --- a/assets/queries/cloudFormation/aws/s3_bucket_without_restriction_of_public_bucket/query.rego +++ b/assets/queries/cloudFormation/aws/s3_bucket_without_restriction_of_public_bucket/query.rego @@ -46,7 +46,7 @@ CxPolicy[result] { resource.Type == "AWS::S3::Bucket" PublicAccessBlockConfiguration := resource.Properties.PublicAccessBlockConfiguration - PublicAccessBlockConfiguration.RestrictPublicBuckets == false + cf_lib.isCloudFormationFalse(PublicAccessBlockConfiguration.RestrictPublicBuckets) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/s3_bucket_without_restriction_of_public_bucket/test/negative3.yaml b/assets/queries/cloudFormation/aws/s3_bucket_without_restriction_of_public_bucket/test/negative3.yaml new file mode 100644 index 00000000000..40d16c7688f --- /dev/null +++ b/assets/queries/cloudFormation/aws/s3_bucket_without_restriction_of_public_bucket/test/negative3.yaml @@ -0,0 +1,9 @@ +Resources: + Bucket1: + Type: AWS::S3::Bucket + Properties: + PublicAccessBlockConfiguration: + BlockPublicAcls : "true" + BlockPublicPolicy : "true" + IgnorePublicAcls : "true" + RestrictPublicBuckets : "true" \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/s3_bucket_without_restriction_of_public_bucket/test/positive3.yaml b/assets/queries/cloudFormation/aws/s3_bucket_without_restriction_of_public_bucket/test/positive3.yaml new file mode 100644 index 00000000000..cba247e31db --- /dev/null +++ b/assets/queries/cloudFormation/aws/s3_bucket_without_restriction_of_public_bucket/test/positive3.yaml @@ -0,0 +1,21 @@ +Resources: + Bucket11: + Type: AWS::S3::Bucket + Properties: +--- +Resources: + Bucket12: + Type: AWS::S3::Bucket + Properties: + PublicAccessBlockConfiguration: + BlockPublicPolicy : "true" +--- +Resources: + Bucket13: + Type: AWS::S3::Bucket + Properties: + PublicAccessBlockConfiguration: + BlockPublicAcls: "false" + BlockPublicPolicy : "true" + IgnorePublicAcls : "false" + RestrictPublicBuckets : "false" diff --git a/assets/queries/cloudFormation/aws/s3_bucket_without_restriction_of_public_bucket/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/s3_bucket_without_restriction_of_public_bucket/test/positive_expected_result.json index a27fd0546b0..5f10f50b495 100755 --- a/assets/queries/cloudFormation/aws/s3_bucket_without_restriction_of_public_bucket/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/s3_bucket_without_restriction_of_public_bucket/test/positive_expected_result.json @@ -22,5 +22,23 @@ "severity": "MEDIUM", "line": 10, "filename": "positive2.json" + }, + { + "queryName": "S3 Bucket Without Restriction Of Public Bucket", + "severity": "MEDIUM", + "line": 4, + "filename": "positive3.yaml" + }, + { + "queryName": "S3 Bucket Without Restriction Of Public Bucket", + "severity": "MEDIUM", + "line": 10, + "filename": "positive3.yaml" + }, + { + "queryName": "S3 Bucket Without Restriction Of Public Bucket", + "severity": "MEDIUM", + "line": 21, + "filename": "positive3.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/s3_bucket_without_ssl_in_write_actions/query.rego b/assets/queries/cloudFormation/aws/s3_bucket_without_ssl_in_write_actions/query.rego index 62ff067508c..fe0c10337a0 100644 --- a/assets/queries/cloudFormation/aws/s3_bucket_without_ssl_in_write_actions/query.rego +++ b/assets/queries/cloudFormation/aws/s3_bucket_without_ssl_in_write_actions/query.rego @@ -68,16 +68,13 @@ isUnsafeAction("s3:*") = true isUnsafeAction("s3:PutObject") = true -equalsFalse("false") = true - -equalsFalse(false) = true isValidSslPolicyStatement(stmt) { is_array(stmt) st := stmt[s] st.Effect == "Deny" isUnsafeAction(st.Action) - equalsFalse(st.Condition.Bool["aws:SecureTransport"]) + cf_lib.isCloudFormationFalse(st.Condition.Bool["aws:SecureTransport"]) } else { is_array(stmt) st := stmt[s] @@ -85,20 +82,20 @@ isValidSslPolicyStatement(stmt) { is_array(st.Action) action := st.Action[i] isUnsafeAction(action) - equalsFalse(st.Condition.Bool["aws:SecureTransport"]) + cf_lib.isCloudFormationFalse(st.Condition.Bool["aws:SecureTransport"]) } else { is_object(stmt) stmt.Effect == "Deny" isUnsafeAction(stmt.Action) - equalsFalse(stmt.Condition.Bool["aws:SecureTransport"]) + cf_lib.isCloudFormationFalse(stmt.Condition.Bool["aws:SecureTransport"]) } else { is_array(stmt) st := stmt[s] st.Effect == "Allow" isUnsafeAction(st.Action) - not equalsFalse(st.Condition.Bool["aws:SecureTransport"]) + not cf_lib.isCloudFormationFalse(st.Condition.Bool["aws:SecureTransport"]) } else { is_array(stmt) st := stmt[s] @@ -106,11 +103,11 @@ else { is_array(st.Action) action := st.Action[i] isUnsafeAction(action) - not equalsFalse(st.Condition.Bool["aws:SecureTransport"]) + not cf_lib.isCloudFormationFalse(st.Condition.Bool["aws:SecureTransport"]) } else { is_object(stmt) stmt.Effect == "Allow" isUnsafeAction(stmt.Action) - not equalsFalse(stmt.Condition.Bool["aws:SecureTransport"]) + not cf_lib.isCloudFormationFalse(stmt.Condition.Bool["aws:SecureTransport"]) } diff --git a/assets/queries/cloudFormation/aws/secure_ciphers_disabled/query.rego b/assets/queries/cloudFormation/aws/secure_ciphers_disabled/query.rego index f4091549fe7..c60e170291c 100644 --- a/assets/queries/cloudFormation/aws/secure_ciphers_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/secure_ciphers_disabled/query.rego @@ -5,7 +5,7 @@ import data.generic.cloudformation as cf_lib CxPolicy[result] { resource := input.document[i].Resources[name] - resource.Properties.ViewerCertificate.CloudFrontDefaultCertificate == false + cf_lib.isCloudFormationFalse(resource.Properties.ViewerCertificate.CloudFrontDefaultCertificate) not commonLib.inArray({"TLSv1.1", "TLSv1.2"}, resource.Properties.ViewerCertificate.MinimumProtocolVersion) result := { diff --git a/assets/queries/cloudFormation/aws/secure_ciphers_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/secure_ciphers_disabled/test/negative3.yaml new file mode 100644 index 00000000000..47cbc5a4010 --- /dev/null +++ b/assets/queries/cloudFormation/aws/secure_ciphers_disabled/test/negative3.yaml @@ -0,0 +1,25 @@ +#this code is a correct code for which the query should not find any result +AWSTemplateFormatVersion: "2010-09-09" +Resources: + cloudfrontdistribution: + Type: AWS::CloudFront::Distribution + Properties: + DistributionConfig: + CacheBehaviors: + - LambdaFunctionAssociations: + - EventType: viewer-request + LambdaFunctionARN: examp + DefaultCacheBehavior: + LambdaFunctionAssociations: + - EventType: viewer-request + LambdaFunctionARN: examp + IPV6Enabled: "true" + Origins: + - CustomOriginConfig: + OriginKeepaliveTimeout: 60 + OriginReadTimeout: 30 + Tags: + - Key: name + Value: example + ViewerCertificate: + CloudFrontDefaultCertificate: "true" \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/secure_ciphers_disabled/test/positive3.yaml b/assets/queries/cloudFormation/aws/secure_ciphers_disabled/test/positive3.yaml new file mode 100644 index 00000000000..0c6f6347e4a --- /dev/null +++ b/assets/queries/cloudFormation/aws/secure_ciphers_disabled/test/positive3.yaml @@ -0,0 +1,26 @@ +#this is a problematic code where the query should report a result(s) +AWSTemplateFormatVersion: "2010-09-09" +Resources: + cloudfrontdistribution: + Type: AWS::CloudFront::Distribution + Properties: + DistributionConfig: + CacheBehaviors: + - LambdaFunctionAssociations: + - EventType: viewer-request + LambdaFunctionARN: examp + DefaultCacheBehavior: + LambdaFunctionAssociations: + - EventType: viewer-request + LambdaFunctionARN: examp + IPV6Enabled: "true" + Origins: + - CustomOriginConfig: + OriginKeepaliveTimeout: 60 + OriginReadTimeout: 30 + Tags: + - Key: name + Value: example + ViewerCertificate: + CloudFrontDefaultCertificate: "false" + MinimumProtocolVersion: SSLv3 \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/secure_ciphers_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/secure_ciphers_disabled/test/positive_expected_result.json index 66ce13e9eb7..818af741276 100644 --- a/assets/queries/cloudFormation/aws/secure_ciphers_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/secure_ciphers_disabled/test/positive_expected_result.json @@ -10,5 +10,11 @@ "severity": "MEDIUM", "line": 44, "fileName": "positive2.json" + }, + { + "queryName": "Secure Ciphers Disabled", + "severity": "MEDIUM", + "line": 26, + "fileName": "positive3.yaml" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/stack_retention_disabled/query.rego b/assets/queries/cloudFormation/aws/stack_retention_disabled/query.rego index 42b9ee932c1..51a2406f03c 100644 --- a/assets/queries/cloudFormation/aws/stack_retention_disabled/query.rego +++ b/assets/queries/cloudFormation/aws/stack_retention_disabled/query.rego @@ -46,7 +46,7 @@ CxPolicy[result] { autoDeployment := resource.Properties.AutoDeployment - autoDeployment.Enabled == false + cf_lib.isCloudFormationFalse(autoDeployment.Enabled) result := { "documentId": input.document[i].id, @@ -85,7 +85,7 @@ CxPolicy[result] { autoDeployment.Enabled - autoDeployment.RetainStacksOnAccountRemoval == false + cf_lib.isCloudFormationFalse(autoDeployment.RetainStacksOnAccountRemoval) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/stack_retention_disabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/stack_retention_disabled/test/negative3.yaml new file mode 100644 index 00000000000..fdd79c12fbc --- /dev/null +++ b/assets/queries/cloudFormation/aws/stack_retention_disabled/test/negative3.yaml @@ -0,0 +1,11 @@ +AWSTemplateFormatVersion: '2010-09-09' +Resources: + stackset: + Type: AWS::CloudFormation::StackSet + Properties: + PermissionModel: SERVICE_MANAGED + StackSetName: some_stack_name + TemplateURL: some_stack_link + AutoDeployment: + Enabled: "true" + RetainStacksOnAccountRemoval: "true" diff --git a/assets/queries/cloudFormation/aws/stack_retention_disabled/test/positive3.yaml b/assets/queries/cloudFormation/aws/stack_retention_disabled/test/positive3.yaml new file mode 100644 index 00000000000..98f235c78ae --- /dev/null +++ b/assets/queries/cloudFormation/aws/stack_retention_disabled/test/positive3.yaml @@ -0,0 +1,42 @@ +AWSTemplateFormatVersion: '2010-09-09' +Resources: + stackset3: + Type: AWS::CloudFormation::StackSet + Properties: + PermissionModel: SERVICE_MANAGED + StackSetName: some_stack_name + TemplateURL: some_stack_link + AutoDeployment: + Enabled: "true" + RetainStacksOnAccountRemoval: "false" + stackset4: + Type: AWS::CloudFormation::StackSet + Properties: + PermissionModel: SERVICE_MANAGED + StackSetName: some_stack_name + TemplateURL: some_stack_link + AutoDeployment: + Enabled: "true" + stackset5: + Type: AWS::CloudFormation::StackSet + Properties: + PermissionModel: SERVICE_MANAGED + StackSetName: some_stack_name + TemplateURL: some_stack_link + AutoDeployment: + Enabled: "false" + RetainStacksOnAccountRemoval: "true" + stackset6: + Type: AWS::CloudFormation::StackSet + Properties: + PermissionModel: SERVICE_MANAGED + StackSetName: some_stack_name + TemplateURL: some_stack_link + AutoDeployment: + RetainStacksOnAccountRemoval: "false" + stackset7: + Type: AWS::CloudFormation::StackSet + Properties: + PermissionModel: SERVICE_MANAGED + StackSetName: some_stack_name + TemplateURL: some_stack_link diff --git a/assets/queries/cloudFormation/aws/stack_retention_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/stack_retention_disabled/test/positive_expected_result.json index 842b5831c0a..f49d35cf0ce 100644 --- a/assets/queries/cloudFormation/aws/stack_retention_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/stack_retention_disabled/test/positive_expected_result.json @@ -58,5 +58,35 @@ "severity": "MEDIUM", "line": 52, "fileName": "positive2.json" + }, + { + "queryName": "Stack Retention Disabled", + "severity": "MEDIUM", + "line": 11, + "fileName": "positive3.yaml" + }, + { + "queryName": "Stack Retention Disabled", + "severity": "MEDIUM", + "line": 18, + "fileName": "positive3.yaml" + }, + { + "queryName": "Stack Retention Disabled", + "severity": "MEDIUM", + "line": 27, + "fileName": "positive3.yaml" + }, + { + "queryName": "Stack Retention Disabled", + "severity": "MEDIUM", + "line": 35, + "fileName": "positive3.yaml" + }, + { + "queryName": "Stack Retention Disabled", + "severity": "MEDIUM", + "line": 39, + "fileName": "positive3.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/unscanned_ecr_image/query.rego b/assets/queries/cloudFormation/aws/unscanned_ecr_image/query.rego index 0d87fd26003..88145ba95f7 100644 --- a/assets/queries/cloudFormation/aws/unscanned_ecr_image/query.rego +++ b/assets/queries/cloudFormation/aws/unscanned_ecr_image/query.rego @@ -26,7 +26,7 @@ CxPolicy[result] { resource.Type == "AWS::ECR::Repository" properties := resource.Properties - isResFalse(properties.ImageScanningConfiguration.ScanOnPush) + cf_lib.isCloudFormationFalse(properties.ImageScanningConfiguration.ScanOnPush) result := { "documentId": input.document[i].id, @@ -39,8 +39,3 @@ CxPolicy[result] { } } -isResFalse(answer) { - answer == "false" -} else { - answer == false -} diff --git a/assets/queries/cloudFormation/aws/unscanned_ecr_image/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/unscanned_ecr_image/test/positive_expected_result.json index e970eb66f59..ea5c7178c23 100644 --- a/assets/queries/cloudFormation/aws/unscanned_ecr_image/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/unscanned_ecr_image/test/positive_expected_result.json @@ -6,10 +6,10 @@ "fileName": "positive1.yaml" }, { - "fileName": "positive2.yaml", "queryName": "Unscanned ECR Image", "severity": "LOW", - "line": 8 + "line": 8, + "fileName": "positive2.yaml" }, { "queryName": "Unscanned ECR Image", @@ -18,9 +18,9 @@ "fileName": "positive3.json" }, { - "line": 9, - "fileName": "positive4.json", "queryName": "Unscanned ECR Image", - "severity": "LOW" + "severity": "LOW", + "line": 9, + "fileName": "positive4.json" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/user_iam_missing_password_reset_required/query.rego b/assets/queries/cloudFormation/aws/user_iam_missing_password_reset_required/query.rego index 9b931c16023..28fff307a1b 100644 --- a/assets/queries/cloudFormation/aws/user_iam_missing_password_reset_required/query.rego +++ b/assets/queries/cloudFormation/aws/user_iam_missing_password_reset_required/query.rego @@ -8,7 +8,7 @@ CxPolicy[result] { resource.Type == "AWS::IAM::User" loginProfile := resource.Properties.LoginProfile loginProfile.Password - loginProfile.PasswordResetRequired == false + cf_lib.isCloudFormationFalse(loginProfile.PasswordResetRequired) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws/user_iam_missing_password_reset_required/test/negative1.yaml b/assets/queries/cloudFormation/aws/user_iam_missing_password_reset_required/test/negative1.yaml index 77378213ddd..48e6f2be514 100644 --- a/assets/queries/cloudFormation/aws/user_iam_missing_password_reset_required/test/negative1.yaml +++ b/assets/queries/cloudFormation/aws/user_iam_missing_password_reset_required/test/negative1.yaml @@ -7,7 +7,7 @@ Resources: Path: "/" LoginProfile: Password: myP@ssW0rd - PasswordResetRequired: true + PasswordResetRequired: "true" Policies: - PolicyName: giveaccesstoqueueonly PolicyDocument: diff --git a/assets/queries/cloudFormation/aws/user_iam_missing_password_reset_required/test/negative3.yaml b/assets/queries/cloudFormation/aws/user_iam_missing_password_reset_required/test/negative3.yaml new file mode 100644 index 00000000000..77378213ddd --- /dev/null +++ b/assets/queries/cloudFormation/aws/user_iam_missing_password_reset_required/test/negative3.yaml @@ -0,0 +1,25 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: A sample template +Resources: + myuser: + Type: AWS::IAM::User + Properties: + Path: "/" + LoginProfile: + Password: myP@ssW0rd + PasswordResetRequired: true + Policies: + - PolicyName: giveaccesstoqueueonly + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - sqs:* + Resource: + - !GetAtt myqueue.Arn + - Effect: Deny + Action: + - sqs:* + NotResource: + - !GetAtt myqueue.Arn \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/user_iam_missing_password_reset_required/test/positive7.yaml b/assets/queries/cloudFormation/aws/user_iam_missing_password_reset_required/test/positive7.yaml new file mode 100644 index 00000000000..fc862e8cf77 --- /dev/null +++ b/assets/queries/cloudFormation/aws/user_iam_missing_password_reset_required/test/positive7.yaml @@ -0,0 +1,25 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: A sample template +Resources: + myuser: + Type: AWS::IAM::User + Properties: + Path: "/" + LoginProfile: + Password: myP@ssW0rd + PasswordResetRequired: "false" + Policies: + - PolicyName: giveaccesstoqueueonly + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - sqs:* + Resource: + - !GetAtt myqueue.Arn + - Effect: Deny + Action: + - sqs:* + NotResource: + - !GetAtt myqueue.Arn diff --git a/assets/queries/cloudFormation/aws/user_iam_missing_password_reset_required/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/user_iam_missing_password_reset_required/test/positive_expected_result.json index edae58cbd7d..9bb7a0524e4 100644 --- a/assets/queries/cloudFormation/aws/user_iam_missing_password_reset_required/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/user_iam_missing_password_reset_required/test/positive_expected_result.json @@ -30,9 +30,15 @@ "fileName": "positive5.json" }, { + "queryName": "IAM User Without Password Reset", + "severity": "MEDIUM", "line": 7, - "fileName": "positive6.json", + "fileName": "positive6.json" + }, + { "queryName": "IAM User Without Password Reset", - "severity": "MEDIUM" + "severity": "MEDIUM", + "line": 10, + "fileName": "positive7.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/query.rego b/assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/query.rego index d6226c76659..343b14af4c1 100644 --- a/assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/query.rego +++ b/assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/query.rego @@ -10,7 +10,7 @@ CxPolicy[result] { resource.Type == "AWS::CloudFront::Distribution" value := resource.Properties.DistributionConfig.ViewerCertificate.CloudfrontDefaultCertificate - isAttrTrue(value) + cf_lib.isCloudFormationTrue(value) result := { "documentId": input.document[i].id, @@ -46,12 +46,6 @@ CxPolicy[result] { } } -isAttrTrue(value) { - value == "true" -} else { - value == true -} - hasCustomConfig(viewerCertificate) { common_lib.valid_key(viewerCertificate, "IamCertificateId") } diff --git a/assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive3.yaml b/assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive1.yaml similarity index 58% rename from assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive3.yaml rename to assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive1.yaml index 228a53746c0..75007d0f6ec 100644 --- a/assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive3.yaml +++ b/assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive1.yaml @@ -5,4 +5,4 @@ Resources: Properties: DistributionConfig: ViewerCertificate: - CloudfrontDefaultCertificate: true + AcmCertificateArn: arn:aws:autoscaling:us-west-2:123456789012:autoScalingGroup:a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 diff --git a/assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive2.yaml b/assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive2.yaml index 75007d0f6ec..228a53746c0 100644 --- a/assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive2.yaml +++ b/assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive2.yaml @@ -5,4 +5,4 @@ Resources: Properties: DistributionConfig: ViewerCertificate: - AcmCertificateArn: arn:aws:autoscaling:us-west-2:123456789012:autoScalingGroup:a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 + CloudfrontDefaultCertificate: true diff --git a/assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive5.json b/assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive3.json similarity index 100% rename from assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive5.json rename to assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive3.json diff --git a/assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive6.json b/assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive4.json similarity index 100% rename from assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive6.json rename to assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive4.json diff --git a/assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive_expected_result.json index 1907f878ba1..efa932ba894 100644 --- a/assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/vulnerable_default_ssl_certificate/test/positive_expected_result.json @@ -1,38 +1,38 @@ [ { - "fileName": "positive2.yaml", "queryName": "Vulnerable Default SSL Certificate", "severity": "MEDIUM", - "line": 7 + "line": 7, + "fileName": "positive1.yaml" }, { - "fileName": "positive2.yaml", "queryName": "Vulnerable Default SSL Certificate", "severity": "MEDIUM", - "line": 7 + "line": 7, + "fileName": "positive1.yaml" }, { - "fileName": "positive3.yaml", "queryName": "Vulnerable Default SSL Certificate", "severity": "MEDIUM", - "line": 8 + "line": 8, + "fileName": "positive2.yaml" }, { "queryName": "Vulnerable Default SSL Certificate", "severity": "MEDIUM", "line": 8, - "fileName": "positive5.json" + "fileName": "positive3.json" }, { "queryName": "Vulnerable Default SSL Certificate", "severity": "MEDIUM", "line": 8, - "fileName": "positive5.json" + "fileName": "positive3.json" }, { "queryName": "Vulnerable Default SSL Certificate", "severity": "MEDIUM", "line": 9, - "fileName": "positive6.json" + "fileName": "positive4.json" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/workspace_without_encryption/query.rego b/assets/queries/cloudFormation/aws/workspace_without_encryption/query.rego index 8a8d0493e9a..327f621058a 100644 --- a/assets/queries/cloudFormation/aws/workspace_without_encryption/query.rego +++ b/assets/queries/cloudFormation/aws/workspace_without_encryption/query.rego @@ -9,8 +9,8 @@ CxPolicy[result] { document.Resources[workspaceName].Type == "AWS::WorkSpaces::Workspace" workspace := document.Resources[workspaceName] - # The UserVolumeEncryptionEnabled property is defined, but is set to false - not isTrue(workspace.Properties.UserVolumeEncryptionEnabled) + # The UserVolumeEncryptionEnabled property is defined, but is not set to true + not cf_lib.isCloudFormationTrue(workspace.Properties.UserVolumeEncryptionEnabled) result := { "documentId": document.id, @@ -19,7 +19,7 @@ CxPolicy[result] { "searchKey": sprintf("Resources.%s.Properties.UserVolumeEncryptionEnabled", [workspaceName]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("Resources.%s.Properties.UserVolumeEncryptionEnabled should be set to true", [workspaceName]), - "keyActualValue": sprintf("Resources.%s.Properties.UserVolumeEncryptionEnabled is set to false", [workspaceName]), + "keyActualValue": sprintf("Resources.%s.Properties.UserVolumeEncryptionEnabled is not set to true", [workspaceName]), } } @@ -43,6 +43,3 @@ CxPolicy[result] { } } -isTrue(true) = true - -isTrue("true") = true diff --git a/assets/queries/cloudFormation/aws/workspace_without_encryption/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/workspace_without_encryption/test/positive_expected_result.json index 69d5a610e77..492408cd150 100644 --- a/assets/queries/cloudFormation/aws/workspace_without_encryption/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/workspace_without_encryption/test/positive_expected_result.json @@ -1,15 +1,15 @@ [ { - "line": 14, - "fileName": "positive2.yaml", "queryName": "Workspace Without Encryption", - "severity": "HIGH" + "severity": "HIGH", + "line": 14, + "fileName": "positive2.yaml" }, { - "fileName": "positive1.yaml", "queryName": "Workspace Without Encryption", "severity": "HIGH", - "line": 4 + "line": 4, + "fileName": "positive1.yaml" }, { "queryName": "Workspace Without Encryption", @@ -18,9 +18,9 @@ "fileName": "positive3.json" }, { + "queryName": "Workspace Without Encryption", "severity": "HIGH", "line": 17, - "fileName": "positive4.json", - "queryName": "Workspace Without Encryption" + "fileName": "positive4.json" } ] \ No newline at end of file From f21ca15f48c3784a7753eb9b0495ac92db66d00a Mon Sep 17 00:00:00 2001 From: Andre Pereira <219305055+cx-andre-pereira@users.noreply.github.com> Date: Thu, 24 Jul 2025 15:28:23 +0100 Subject: [PATCH 02/13] Cloudformation/aws_bom --- .../cloudFormation/aws_bom/dynamo/query.rego | 2 +- .../aws_bom/dynamo/test/positive5.yaml | 40 +++++++++++++++++++ .../dynamo/test/positive_expected_result.json | 6 +++ .../cloudFormation/aws_bom/mq/query.rego | 2 +- .../aws_bom/mq/test/positive3.yaml | 24 +++++++++++ .../mq/test/positive_expected_result.json | 6 +++ .../cloudFormation/aws_bom/rds/query.rego | 14 +++---- .../aws_bom/rds/test/positive7.yaml | 38 ++++++++++++++++++ .../rds/test/positive_expected_result.json | 6 +++ .../aws_bom/s3_bucket/query.rego | 4 +- 10 files changed, 131 insertions(+), 11 deletions(-) create mode 100644 assets/queries/cloudFormation/aws_bom/dynamo/test/positive5.yaml create mode 100644 assets/queries/cloudFormation/aws_bom/mq/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws_bom/rds/test/positive7.yaml diff --git a/assets/queries/cloudFormation/aws_bom/dynamo/query.rego b/assets/queries/cloudFormation/aws_bom/dynamo/query.rego index de5bcea2534..91a727a46e3 100644 --- a/assets/queries/cloudFormation/aws_bom/dynamo/query.rego +++ b/assets/queries/cloudFormation/aws_bom/dynamo/query.rego @@ -84,7 +84,7 @@ has_all_or_dynamob_arn(arn, table_name){ get_encryption(resource) = encryption{ sse := resource.Properties.SSESpecification - sse.SSEEnabled == true + cf_lib.isCloudFormationTrue(sse.SSEEnabled) encryption := "encrypted" } else = encryption{ encryption := "unencrypted" diff --git a/assets/queries/cloudFormation/aws_bom/dynamo/test/positive5.yaml b/assets/queries/cloudFormation/aws_bom/dynamo/test/positive5.yaml new file mode 100644 index 00000000000..3511f659a7f --- /dev/null +++ b/assets/queries/cloudFormation/aws_bom/dynamo/test/positive5.yaml @@ -0,0 +1,40 @@ +AWSTemplateFormatVersion: '2010-09-09' +Resources: + DynamoDBEndpoint: + Type: "AWS::EC2::VPCEndpoint" + Properties: + RouteTableIds: + - !Ref PublicRouteTable + - !Ref Private0RouteTable + - !Ref Private1RouteTable + - !Ref Private2RouteTable + ServiceName: + !Sub "com.amazonaws.${AWS::Region}.dynamodb" + VpcId: !Ref VPC + PolicyDocument: { + "Id": "Policy", + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "Statement", + "Action": "dynamodb:*", + "Effect": "Allow", + "Resource": "arn:aws:dynamodb:ap-southeast-2:123412341234:table/test", + "Principal": "*" + } + ] + } + DynamoDBOnDemandTable2: + Type: "AWS::DynamoDB::Table" + Properties: + TableName: test + AttributeDefinitions: + - AttributeName: pk + AttributeType: S + KeySchema: + - AttributeName: pk + KeyType: HASH + BillingMode: PAY_PER_REQUEST + SSESpecification: + SSEEnabled: "false" + SSEType: "KMS" diff --git a/assets/queries/cloudFormation/aws_bom/dynamo/test/positive_expected_result.json b/assets/queries/cloudFormation/aws_bom/dynamo/test/positive_expected_result.json index e2666a30034..76e5be3bb50 100644 --- a/assets/queries/cloudFormation/aws_bom/dynamo/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws_bom/dynamo/test/positive_expected_result.json @@ -22,5 +22,11 @@ "severity": "TRACE", "line": 3, "fileName": "positive4.yaml" + }, + { + "queryName": "BOM - AWS DynamoDB", + "severity": "TRACE", + "line": 27, + "fileName": "positive5.yaml" } ] diff --git a/assets/queries/cloudFormation/aws_bom/mq/query.rego b/assets/queries/cloudFormation/aws_bom/mq/query.rego index 221bce8ffe5..127841b840f 100644 --- a/assets/queries/cloudFormation/aws_bom/mq/query.rego +++ b/assets/queries/cloudFormation/aws_bom/mq/query.rego @@ -31,7 +31,7 @@ CxPolicy[result] { } check_publicly_accessible(resource) = accessibility { - resource.Properties.PubliclyAccessible == true + cf_lib.isCloudFormationTrue(resource.Properties.PubliclyAccessible) accessibility := "public" } else = accessibility { accessibility := "private" diff --git a/assets/queries/cloudFormation/aws_bom/mq/test/positive3.yaml b/assets/queries/cloudFormation/aws_bom/mq/test/positive3.yaml new file mode 100644 index 00000000000..3409ba5b986 --- /dev/null +++ b/assets/queries/cloudFormation/aws_bom/mq/test/positive3.yaml @@ -0,0 +1,24 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: "Create a basic ActiveMQ broker" +Resources: + BasicBroker: + Type: "AWS::AmazonMQ::Broker" + Properties: + AutoMinorVersionUpgrade: "false" + BrokerName: MyBasicBroker + DeploymentMode: SINGLE_INSTANCE + EncryptionOptions: + UseAwsOwnedKey: true + EngineType: ActiveMQ + EngineVersion: "5.15.0" + HostInstanceType: mq.t2.micro + PubliclyAccessible: "true" + Users: + - + ConsoleAccess: "true" + Groups: + - MyGroup + Password: + Ref: "BrokerPassword" + Username: + Ref: "BrokerUsername" diff --git a/assets/queries/cloudFormation/aws_bom/mq/test/positive_expected_result.json b/assets/queries/cloudFormation/aws_bom/mq/test/positive_expected_result.json index 909c0806e2f..f2de8ddc34b 100644 --- a/assets/queries/cloudFormation/aws_bom/mq/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws_bom/mq/test/positive_expected_result.json @@ -10,5 +10,11 @@ "severity": "TRACE", "line": 5, "fileName": "positive2.json" + }, + { + "queryName": "BOM - AWS MQ", + "severity": "TRACE", + "line": 4, + "fileName": "positive3.yaml" } ] diff --git a/assets/queries/cloudFormation/aws_bom/rds/query.rego b/assets/queries/cloudFormation/aws_bom/rds/query.rego index b8c23231ae9..9d25fe5e8ca 100644 --- a/assets/queries/cloudFormation/aws_bom/rds/query.rego +++ b/assets/queries/cloudFormation/aws_bom/rds/query.rego @@ -35,10 +35,10 @@ CxPolicy[result] { ## get accessibility functions get_resource_accessibility(resource) = accessibility{ - resource.Properties.PubliclyAccessible == true + cf_lib.isCloudFormationTrue(resource.Properties.PubliclyAccessible) accessibility:= "public" } else = accessibility{ - resource.Properties.PubliclyAccessible == false + cf_lib.isCloudFormationFalse(resource.Properties.PubliclyAccessible) accessibility:= "private" } else = accessibility{ not common_lib.valid_key(resource,"PubliclyAccessible") @@ -80,10 +80,10 @@ get_db_instance_encryption(resource) = encryption{ # get encytion for instances with engines that are not aurora get_enc_for_not_aurora(resource) = encryption{ - resource.Properties.StorageEncrypted == true + cf_lib.isCloudFormationTrue(resource.Properties.StorageEncrypted) encryption := "encrypted" } else = encryption{ - resource.Properties.StorageEncrypted == false + cf_lib.isCloudFormationFalse(resource.Properties.StorageEncrypted) encryption := "unencrypted" } else = encryption{ not common_lib.valid_key(resource.Properties, "StorageEncrypted") @@ -106,7 +106,7 @@ get_enc_for_not_aurora(resource) = encryption{ } get_encryption(resource) = encryption{ - resource.Properties.StorageEncrypted == true + cf_lib.isCloudFormationTrue(resource.Properties.StorageEncrypted) encryption := "encrypted" } else = encryption{ encryption := "unencrypted" @@ -124,10 +124,10 @@ get_enc_for_aurora(resource) = encryption{ # get encytion for for the cluster get_cluster_enc(resource)= encryption{ - resource.Properties.StorageEncrypted == true + cf_lib.isCloudFormationTrue(resource.Properties.StorageEncrypted) encryption := "encrypted" } else = encryption{ - resource.Properties.StorageEncrypted == false + cf_lib.isCloudFormationFalse(resource.Properties.StorageEncrypted) encryption := "unencrypted" } else = encryption{ not common_lib.valid_key(resource.Properties, "SourceDBClusterIdentifier ") diff --git a/assets/queries/cloudFormation/aws_bom/rds/test/positive7.yaml b/assets/queries/cloudFormation/aws_bom/rds/test/positive7.yaml new file mode 100644 index 00000000000..830ce9d3440 --- /dev/null +++ b/assets/queries/cloudFormation/aws_bom/rds/test/positive7.yaml @@ -0,0 +1,38 @@ +AWSTemplateFormatVersion: '2010-09-09' +Resources: + DBInstanceSample5: + Type: AWS::RDS::DBInstance + Properties: + Engine: aurora + PubliclyAccessible: "true" + DBClusterIdentifier: DBClusterSample5 + DBClusterSample5: + Type: 'AWS::RDS::DBCluster' + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + DBClusterIdentifier: my-serverless-cluster + Engine: aurora + EngineVersion: 5.6.10a + EngineMode: serverless + SourceDBClusterIdentifier: !Ref DBClusterSampleRef5 + ScalingConfiguration: + AutoPause: true + MinCapacity: 4 + MaxCapacity: 32 + SecondsUntilAutoPause: 1000 + DBClusterSampleRef5: + Type: 'AWS::RDS::DBCluster' + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + DBClusterIdentifier: my-serverless-cluster + Engine: aurora + EngineVersion: 5.6.10a + EngineMode: serverless + StorageEncrypted: "true" + ScalingConfiguration: + AutoPause: true + MinCapacity: 4 + MaxCapacity: 32 + SecondsUntilAutoPause: 1000 diff --git a/assets/queries/cloudFormation/aws_bom/rds/test/positive_expected_result.json b/assets/queries/cloudFormation/aws_bom/rds/test/positive_expected_result.json index e839529e01e..31443e3f791 100644 --- a/assets/queries/cloudFormation/aws_bom/rds/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws_bom/rds/test/positive_expected_result.json @@ -46,5 +46,11 @@ "severity": "TRACE", "line": 3, "fileName": "positive6.yaml" + }, + { + "queryName": "BOM - AWS RDS", + "severity": "TRACE", + "line": 3, + "fileName": "positive7.yaml" } ] diff --git a/assets/queries/cloudFormation/aws_bom/s3_bucket/query.rego b/assets/queries/cloudFormation/aws_bom/s3_bucket/query.rego index 936d8b2cc9b..f7537231efe 100644 --- a/assets/queries/cloudFormation/aws_bom/s3_bucket/query.rego +++ b/assets/queries/cloudFormation/aws_bom/s3_bucket/query.rego @@ -40,8 +40,8 @@ get_bucket_acl(bucket_resource) = acl { } is_public_access_blocked(properties) { - properties.BlockPublicAcls == true - properties.BlockPublicPolicy == true + cf_lib.isCloudFormationTrue(properties.BlockPublicAcls) + cf_lib.isCloudFormationTrue(properties.BlockPublicPolicy) } get_resource_accessibility(resource, name) = info { From 55686af3707b9c37caa0dda9ccec62c76498bd2b Mon Sep 17 00:00:00 2001 From: Andre Pereira <219305055+cx-andre-pereira@users.noreply.github.com> Date: Thu, 24 Jul 2025 15:31:27 +0100 Subject: [PATCH 03/13] Cloudformation/aws_sam --- .../serverless_api_cache_cluster_disabled/query.rego | 2 +- .../test/negative2.yaml | 10 ++++++++++ .../test/positive3.yaml | 10 ++++++++++ .../test/positive_expected_result.json | 6 ++++++ .../serverless_api_xray_tracing_disabled/query.rego | 2 +- .../test/negative2.yaml | 9 +++++++++ .../test/positive3.yaml | 9 +++++++++ .../test/positive_expected_result.json | 6 ++++++ 8 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 assets/queries/cloudFormation/aws_sam/serverless_api_cache_cluster_disabled/test/negative2.yaml create mode 100644 assets/queries/cloudFormation/aws_sam/serverless_api_cache_cluster_disabled/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws_sam/serverless_api_xray_tracing_disabled/test/negative2.yaml create mode 100644 assets/queries/cloudFormation/aws_sam/serverless_api_xray_tracing_disabled/test/positive3.yaml diff --git a/assets/queries/cloudFormation/aws_sam/serverless_api_cache_cluster_disabled/query.rego b/assets/queries/cloudFormation/aws_sam/serverless_api_cache_cluster_disabled/query.rego index 4777eabf4df..1808ed45193 100644 --- a/assets/queries/cloudFormation/aws_sam/serverless_api_cache_cluster_disabled/query.rego +++ b/assets/queries/cloudFormation/aws_sam/serverless_api_cache_cluster_disabled/query.rego @@ -28,7 +28,7 @@ CxPolicy[result] { resource.Type == "AWS::Serverless::Api" properties := resource.Properties - properties.CacheClusterEnabled == false + cf_lib.isCloudFormationFalse(properties.CacheClusterEnabled) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws_sam/serverless_api_cache_cluster_disabled/test/negative2.yaml b/assets/queries/cloudFormation/aws_sam/serverless_api_cache_cluster_disabled/test/negative2.yaml new file mode 100644 index 00000000000..cb12d7a4d0f --- /dev/null +++ b/assets/queries/cloudFormation/aws_sam/serverless_api_cache_cluster_disabled/test/negative2.yaml @@ -0,0 +1,10 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: AWS SAM template with a simple API definition +Resources: + ApiGatewayApi3: + Type: AWS::Serverless::Api + Properties: + StageName: prod + TracingEnabled: true + CacheClusterEnabled: "true" diff --git a/assets/queries/cloudFormation/aws_sam/serverless_api_cache_cluster_disabled/test/positive3.yaml b/assets/queries/cloudFormation/aws_sam/serverless_api_cache_cluster_disabled/test/positive3.yaml new file mode 100644 index 00000000000..9da21c24bf8 --- /dev/null +++ b/assets/queries/cloudFormation/aws_sam/serverless_api_cache_cluster_disabled/test/positive3.yaml @@ -0,0 +1,10 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: AWS SAM template with a simple API definition +Resources: + ApiGatewayApi2: + Type: AWS::Serverless::Api + Properties: + StageName: prod + TracingEnabled: true + CacheClusterEnabled: "false" diff --git a/assets/queries/cloudFormation/aws_sam/serverless_api_cache_cluster_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws_sam/serverless_api_cache_cluster_disabled/test/positive_expected_result.json index 3cbd4b1a469..16af5f0a76b 100644 --- a/assets/queries/cloudFormation/aws_sam/serverless_api_cache_cluster_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws_sam/serverless_api_cache_cluster_disabled/test/positive_expected_result.json @@ -10,5 +10,11 @@ "severity": "LOW", "line": 10, "fileName": "positive2.yaml" + }, + { + "queryName": "Serverless API Cache Cluster Disabled", + "severity": "LOW", + "line": 10, + "fileName": "positive3.yaml" } ] diff --git a/assets/queries/cloudFormation/aws_sam/serverless_api_xray_tracing_disabled/query.rego b/assets/queries/cloudFormation/aws_sam/serverless_api_xray_tracing_disabled/query.rego index 6cac6bb96ba..dd91d88d581 100644 --- a/assets/queries/cloudFormation/aws_sam/serverless_api_xray_tracing_disabled/query.rego +++ b/assets/queries/cloudFormation/aws_sam/serverless_api_xray_tracing_disabled/query.rego @@ -28,7 +28,7 @@ CxPolicy[result] { resource.Type == "AWS::Serverless::Api" properties := resource.Properties - properties.TracingEnabled == false + cf_lib.isCloudFormationFalse(properties.TracingEnabled) result := { "documentId": input.document[i].id, diff --git a/assets/queries/cloudFormation/aws_sam/serverless_api_xray_tracing_disabled/test/negative2.yaml b/assets/queries/cloudFormation/aws_sam/serverless_api_xray_tracing_disabled/test/negative2.yaml new file mode 100644 index 00000000000..4327bbc8dad --- /dev/null +++ b/assets/queries/cloudFormation/aws_sam/serverless_api_xray_tracing_disabled/test/negative2.yaml @@ -0,0 +1,9 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: AWS SAM template with a simple API definition +Resources: + ApiGatewayApi3: + Type: AWS::Serverless::Api + Properties: + StageName: prod + TracingEnabled: "true" diff --git a/assets/queries/cloudFormation/aws_sam/serverless_api_xray_tracing_disabled/test/positive3.yaml b/assets/queries/cloudFormation/aws_sam/serverless_api_xray_tracing_disabled/test/positive3.yaml new file mode 100644 index 00000000000..2d97a0282f8 --- /dev/null +++ b/assets/queries/cloudFormation/aws_sam/serverless_api_xray_tracing_disabled/test/positive3.yaml @@ -0,0 +1,9 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: AWS SAM template with a simple API definition +Resources: + ApiGatewayApi2: + Type: AWS::Serverless::Api + Properties: + StageName: prod + TracingEnabled: "false" diff --git a/assets/queries/cloudFormation/aws_sam/serverless_api_xray_tracing_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws_sam/serverless_api_xray_tracing_disabled/test/positive_expected_result.json index dc127a8f64f..9b3580ba2f5 100644 --- a/assets/queries/cloudFormation/aws_sam/serverless_api_xray_tracing_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws_sam/serverless_api_xray_tracing_disabled/test/positive_expected_result.json @@ -10,5 +10,11 @@ "severity": "MEDIUM", "line": 9, "fileName": "positive2.yaml" + }, + { + "queryName": "Serverless API X-Ray Tracing Disabled", + "severity": "MEDIUM", + "line": 9, + "fileName": "positive3.yaml" } ] From c9edd41dc543bdaccd854b867297e72eaca67ef3 Mon Sep 17 00:00:00 2001 From: Andre Pereira <219305055+cx-andre-pereira@users.noreply.github.com> Date: Thu, 24 Jul 2025 17:03:42 +0100 Subject: [PATCH 04/13] github guardian FN fix_1 --- .../test/negative7.yaml | 2 +- .../test/positive5.yaml | 2 +- .../test/negative7.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/negative7.yaml b/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/negative7.yaml index 58c484fc2ff..a04cae4bc18 100644 --- a/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/negative7.yaml +++ b/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/negative7.yaml @@ -12,7 +12,7 @@ Resources: Repository: String BasicAuthConfig : EnableBasicAuth: "true" - Password: !Sub '{{resolve:secretsmanager:${MyAmpAppSecretManagerRotater}::password}}' + Password: !Sub '' Username: !Sub '{{resolve:secretsmanager:${MyAmpAppSecretManagerRotater}::username}}' MyAmpAppSecretManagerRotater: Type: AWS::SecretsManager::Secret diff --git a/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive5.yaml b/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive5.yaml index 0cbfa83faf9..0551ab58adf 100644 --- a/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive5.yaml +++ b/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive5.yaml @@ -13,5 +13,5 @@ Resources: Repository: String BasicAuthConfig: EnableBasicAuth: "true" - Password: "@skdsjdk0234!AB" + Password: "" Username: admin diff --git a/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/negative7.yaml b/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/negative7.yaml index 290af9e97f7..ea54d4000f4 100644 --- a/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/negative7.yaml +++ b/assets/queries/cloudFormation/aws/amplify_branch_basic_auth_config_password_exposed/test/negative7.yaml @@ -12,7 +12,7 @@ Resources: Repository: String BasicAuthConfig : EnableBasicAuth: "true" - Password: !Sub '{{resolve:secretsmanager:${MyAmpAppSecretManagerRotater}::password}}' + Password: !Sub '' Username: !Sub '{{resolve:secretsmanager:${MyAmpAppSecretManagerRotater}::username}}' MyAmpAppSecretManagerRotater: Type: AWS::SecretsManager::Secret From bdf34f4d14c6a8351131c383c29c5e16046353e5 Mon Sep 17 00:00:00 2001 From: Andre Pereira <219305055+cx-andre-pereira@users.noreply.github.com> Date: Fri, 25 Jul 2025 14:11:32 +0100 Subject: [PATCH 05/13] fix for expected results 1 --- .../test/positive5.yaml | 15 ++++++++++++--- .../test/positive_expected_result.json | 2 +- .../test/positive_expected_result.json | 2 +- .../test/{positive3.yml => positive3.yaml} | 0 .../test/positive_expected_result.json | 10 +++++----- .../test/positive_expected_result.json | 2 +- 6 files changed, 20 insertions(+), 11 deletions(-) rename assets/queries/cloudFormation/aws/dynamodb_table_not_encrypted/test/{positive3.yml => positive3.yaml} (100%) diff --git a/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive5.yaml b/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive5.yaml index 0551ab58adf..b2ace3d27ac 100644 --- a/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive5.yaml +++ b/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive5.yaml @@ -1,6 +1,15 @@ AWSTemplateFormatVersion: 2010-09-09 +Parameters: + ParentPassword: + Description: 'Password' + Type: String + Default: "@skdsjdk0234!AB" + ParentUsername: + Description: 'Username' + Type: String + Default: "" Resources: - NewAmpApp-1: + NewAmpApp-4: Type: AWS::Amplify::App Properties: BuildSpec: String @@ -13,5 +22,5 @@ Resources: Repository: String BasicAuthConfig: EnableBasicAuth: "true" - Password: "" - Username: admin + Password: !Ref ParentPassword + Username: !Ref ParentUsername diff --git a/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive_expected_result.json index 8d609ba8ecb..f96f04cb1a8 100644 --- a/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/amplify_app_basic_auth_config_password_exposed/test/positive_expected_result.json @@ -26,7 +26,7 @@ { "queryName": "Amplify App Basic Auth Config Password Exposed", "severity": "HIGH", - "line": 16, + "line": 6, "fileName": "positive5.yaml" }, { diff --git a/assets/queries/cloudFormation/aws/config_configuration_aggregator_to_all_regions_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/config_configuration_aggregator_to_all_regions_disabled/test/positive_expected_result.json index 2a915ae18e2..b59fb53e28f 100644 --- a/assets/queries/cloudFormation/aws/config_configuration_aggregator_to_all_regions_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/config_configuration_aggregator_to_all_regions_disabled/test/positive_expected_result.json @@ -52,5 +52,5 @@ "severity": "LOW", "line": 10, "fileName": "positive3.yaml" - }, + } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/dynamodb_table_not_encrypted/test/positive3.yml b/assets/queries/cloudFormation/aws/dynamodb_table_not_encrypted/test/positive3.yaml similarity index 100% rename from assets/queries/cloudFormation/aws/dynamodb_table_not_encrypted/test/positive3.yml rename to assets/queries/cloudFormation/aws/dynamodb_table_not_encrypted/test/positive3.yaml diff --git a/assets/queries/cloudFormation/aws/mq_broker_logging_disabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/mq_broker_logging_disabled/test/positive_expected_result.json index aafc2fcd845..6445a0adcc4 100644 --- a/assets/queries/cloudFormation/aws/mq_broker_logging_disabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/mq_broker_logging_disabled/test/positive_expected_result.json @@ -63,30 +63,30 @@ "queryName": "MQ Broker Logging Disabled", "severity": "MEDIUM", "line": 22, - "fileName": "positive5.yaml" + "fileName": "positive3.yaml" }, { "queryName": "MQ Broker Logging Disabled", "severity": "MEDIUM", "line": 42, - "fileName": "positive5.yaml" + "fileName": "positive3.yaml" }, { "queryName": "MQ Broker Logging Disabled", "severity": "MEDIUM", "line": 63, - "fileName": "positive5.yaml" + "fileName": "positive3.yaml" }, { "queryName": "MQ Broker Logging Disabled", "severity": "MEDIUM", "line": 84, - "fileName": "positive5.yaml" + "fileName": "positive3.yaml" }, { "queryName": "MQ Broker Logging Disabled", "severity": "MEDIUM", "line": 88, - "fileName": "positive5.yaml" + "fileName": "positive3.yaml" } ] diff --git a/assets/queries/cloudFormation/aws/rds_storage_not_encrypted/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/rds_storage_not_encrypted/test/positive_expected_result.json index 163b2c257f4..0e49ea3c58c 100644 --- a/assets/queries/cloudFormation/aws/rds_storage_not_encrypted/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/rds_storage_not_encrypted/test/positive_expected_result.json @@ -27,6 +27,6 @@ "queryName": "RDS Storage Not Encrypted", "severity": "HIGH", "line": 35, - "fileName": "positive5.json" + "fileName": "positive5.yaml" } ] From a665cf0a3dbafe1aba875cf1c82354f35bf8d4fa Mon Sep 17 00:00:00 2001 From: Ricardo Jesus <219317970+cx-ricardo-jesus@users.noreply.github.com> Date: Wed, 20 Aug 2025 11:25:13 +0100 Subject: [PATCH 06/13] query implementation for CloudFormation/AWS --- .../metadata.json | 12 ++++ .../query.rego | 62 +++++++++++++++++++ .../test/negative1.yaml | 15 +++++ .../test/negative2.json | 25 ++++++++ .../test/negative3.yaml | 15 +++++ .../test/negative4.json | 25 ++++++++ .../test/positive1.yaml | 15 +++++ .../test/positive2.json | 25 ++++++++ .../test/positive3.yaml | 14 +++++ .../test/positive4.json | 24 +++++++ .../test/positive5.yaml | 15 +++++ .../test/positive6.json | 25 ++++++++ .../test/positive_expected_result.json | 38 ++++++++++++ 13 files changed, 310 insertions(+) create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/metadata.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/query.rego create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative1.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative2.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative3.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative4.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive1.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive2.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive3.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive4.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive5.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive6.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/metadata.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/metadata.json new file mode 100644 index 00000000000..6b15a808ef5 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/metadata.json @@ -0,0 +1,12 @@ +{ + "id": "6282794f-def8-4d6f-9df6-289318aa42b8", + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "category": "Access Control", + "descriptionText": "IAM Authentication should be enabled to verify the access of users and applications to your databases by enabling IAM policies and multi-factor authentication. This is a safety measure to ensure the protection of newly created databases without the proper IAM policies or in the change of policies in existing databases.", + "descriptionUrl": "https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-enableiamdatabaseauthentication", + "platform": "CloudFormation", + "descriptionID": "6282794f", + "cloudProvider": "aws", + "cwe": "311" +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/query.rego b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/query.rego new file mode 100644 index 00000000000..3933e679eac --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/query.rego @@ -0,0 +1,62 @@ +package Cx + +import data.generic.cloudformation as cf_lib +import data.generic.common as common_lib + +CxPolicy[result] { + docs := input.document[i] + [path, Resources] := walk(docs) + resource := Resources[name] + resource.Type == "AWS::RDS::DBCluster" + + not common_lib.valid_key(resource.Properties, "EnableIAMDatabaseAuthentication") + common_lib.valid_for_iam_engine_and_version_check(resource.Properties, "Engine", "EngineVersion", "DBClusterInstanceClass") + + result := { + "documentId": input.document[i].id, + "resourceType": resource.Type, + "resourceName": cf_lib.get_resource_name(resource, name), + "searchKey": sprintf("Resources.%s.Properties", [name]), + "issueType": "MissingAttribute", + "keyExpectedValue": sprintf("'Resources.%s.Properties.EnableIAMDatabaseAuthentication' should be defined (disabled by default)", [name]), + "keyActualValue": sprintf("'Resources.%s.Properties.EnableIAMDatabaseAuthentication' is not defined (disabled by default)", [name]), + "searchLine": common_lib.build_search_line(["Resources", name, "Properties"], []), + } +} + +CxPolicy[result] { + docs := input.document[i] + [path, Resources] := walk(docs) + resource := Resources[name] + resource.Type == "AWS::RDS::DBCluster" + + common_lib.valid_key(resource.Properties, "EnableIAMDatabaseAuthentication") + cf_lib.isCloudFormationFalse(resource.Properties.EnableIAMDatabaseAuthentication) + common_lib.valid_for_iam_engine_and_version_check(resource.Properties, "Engine", "EngineVersion", "DBClusterInstanceClass") + + result := { + "documentId": input.document[i].id, + "resourceType": resource.Type, + "resourceName": cf_lib.get_resource_name(resource, name), + "searchKey": sprintf("Resources.%s.Properties.EnableIAMDatabaseAuthentication", [name]), + "issueType": "IncorrectValue", + "keyExpectedValue": sprintf("'Resources.%s.Properties.EnableIAMDatabaseAuthentication' should be defined to true", [name]), + "keyActualValue": sprintf("'Resources.%s.Properties.EnableIAMDatabaseAuthentication' is defined to false", [name]), + "searchLine": common_lib.build_search_line(["Resources", name, "Properties", "EnableIAMDatabaseAuthentication"], []) + } +} + +valid_for_iam_engine_and_version_check_edited(resource, engineVar, engineVersionVar, instanceClassVar) { + key_list := [engineVar, engineVersionVar] + contains(lower(resource[engineVar]), "mariadb") + supported_versions := {"10.6", "10.11", "11.4"} + version_check := {x | x := resource[key_list[_]]; contains(x, supported_versions[_])} + count(version_check) > 0 +} else { + engines_that_support_iam := ["aurora-postgresql", "postgres", "mysql", "mariadb"] + contains(lower(resource[engineVar]), engines_that_support_iam[_]) + not common_lib.valid_key(resource, engineVersionVar) +} else { + engines_that_supports_iam := ["aurora-postgresql", "postgres", "mysql"] + contains(lower(resource[engineVar]), engines_that_supports_iam[_]) +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative1.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative1.yaml new file mode 100644 index 00000000000..c4046e1e3ed --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative1.yaml @@ -0,0 +1,15 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + sample: + Type: 'AWS::RDS::DBCluster' + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: true + DBClusterIdentifier: aurora-postgresql-cluster + Engine: aurora-postgresql + EngineVersion: '10.7' + DBClusterParameterGroupName: default.aurora-postgresql10 + EnableCloudwatchLogsExports: + - postgresql + EnableIAMDatabaseAuthentication: true diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative2.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative2.json new file mode 100644 index 00000000000..6d67d93d9e0 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative2.json @@ -0,0 +1,25 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "sample": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": true, + "DBClusterIdentifier": "aurora-postgresql-cluster", + "Engine": "aurora-postgresql", + "EngineVersion": "10.7", + "DBClusterParameterGroupName": "default.aurora-postgresql10", + "EnableCloudwatchLogsExports": [ + "postgresql" + ], + "EnableIAMDatabaseAuthentication": true + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative3.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative3.yaml new file mode 100644 index 00000000000..11a4c40e7f5 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative3.yaml @@ -0,0 +1,15 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + sample: + Type: 'AWS::RDS::DBCluster' + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: true + DBClusterIdentifier: aurora-postgresql-cluster + Engine: aurora-postgresql + EngineVersion: '10.7' + DBClusterParameterGroupName: default.aurora-postgresql10 + EnableCloudwatchLogsExports: + - postgresql + EnableIAMDatabaseAuthentication: "true" diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative4.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative4.json new file mode 100644 index 00000000000..a6aaf69934e --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative4.json @@ -0,0 +1,25 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "sample": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": true, + "DBClusterIdentifier": "aurora-postgresql-cluster", + "Engine": "aurora-postgresql", + "EngineVersion": "10.7", + "DBClusterParameterGroupName": "default.aurora-postgresql10", + "EnableCloudwatchLogsExports": [ + "postgresql" + ], + "EnableIAMDatabaseAuthentication": "true" + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive1.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive1.yaml new file mode 100644 index 00000000000..5a38312eebb --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive1.yaml @@ -0,0 +1,15 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + sample: + Type: 'AWS::RDS::DBCluster' + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: true + DBClusterIdentifier: aurora-postgresql-cluster + Engine: aurora-postgresql + EngineVersion: '10.7' + DBClusterParameterGroupName: default.aurora-postgresql10 + EnableCloudwatchLogsExports: + - postgresql + EnableIAMDatabaseAuthentication: false diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive2.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive2.json new file mode 100644 index 00000000000..06c57c066dd --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive2.json @@ -0,0 +1,25 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "sample": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": true, + "DBClusterIdentifier": "aurora-postgresql-cluster", + "Engine": "aurora-postgresql", + "EngineVersion": "10.7", + "DBClusterParameterGroupName": "default.aurora-postgresql10", + "EnableCloudwatchLogsExports": [ + "postgresql" + ], + "EnableIAMDatabaseAuthentication": false + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive3.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive3.yaml new file mode 100644 index 00000000000..53f57061a60 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive3.yaml @@ -0,0 +1,14 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + sample: + Type: 'AWS::RDS::DBCluster' + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: true + DBClusterIdentifier: aurora-postgresql-cluster + Engine: aurora-postgresql + EngineVersion: '10.7' + DBClusterParameterGroupName: default.aurora-postgresql10 + EnableCloudwatchLogsExports: + - postgresql diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive4.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive4.json new file mode 100644 index 00000000000..33a1ad91f4d --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive4.json @@ -0,0 +1,24 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "sample": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": true, + "DBClusterIdentifier": "aurora-postgresql-cluster", + "Engine": "aurora-postgresql", + "EngineVersion": "10.7", + "DBClusterParameterGroupName": "default.aurora-postgresql10", + "EnableCloudwatchLogsExports": [ + "postgresql" + ] + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive5.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive5.yaml new file mode 100644 index 00000000000..72d1f51ec9b --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive5.yaml @@ -0,0 +1,15 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + sample: + Type: 'AWS::RDS::DBCluster' + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: true + DBClusterIdentifier: aurora-postgresql-cluster + Engine: aurora-postgresql + EngineVersion: '10.7' + DBClusterParameterGroupName: default.aurora-postgresql10 + EnableCloudwatchLogsExports: + - postgresql + EnableIAMDatabaseAuthentication: "false" diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive6.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive6.json new file mode 100644 index 00000000000..48fbe057692 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive6.json @@ -0,0 +1,25 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "sample": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": true, + "DBClusterIdentifier": "aurora-postgresql-cluster", + "Engine": "aurora-postgresql", + "EngineVersion": "10.7", + "DBClusterParameterGroupName": "default.aurora-postgresql10", + "EnableCloudwatchLogsExports": [ + "postgresql" + ], + "EnableIAMDatabaseAuthentication": "false" + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json new file mode 100644 index 00000000000..09bd61d6f77 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json @@ -0,0 +1,38 @@ +[ + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 15, + "fileName": "positive1.yaml" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 21, + "fileName": "positive2.json" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 5, + "fileName": "positive3.yaml" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 6, + "fileName": "positive4.json" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 15, + "fileName": "positive5.yaml" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 21, + "fileName": "positive6.json" + } +] \ No newline at end of file From 31f01eee8484a869a37b0fdc410daca43534061f Mon Sep 17 00:00:00 2001 From: Ricardo Jesus <219317970+cx-ricardo-jesus@users.noreply.github.com> Date: Wed, 20 Aug 2025 13:25:08 +0100 Subject: [PATCH 07/13] query implementation for terraform --- .../aws/iam_db_cluster_auth_not_enabled/query.rego | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/query.rego b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/query.rego index 3933e679eac..ddf67daf24e 100644 --- a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/query.rego +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/query.rego @@ -10,7 +10,7 @@ CxPolicy[result] { resource.Type == "AWS::RDS::DBCluster" not common_lib.valid_key(resource.Properties, "EnableIAMDatabaseAuthentication") - common_lib.valid_for_iam_engine_and_version_check(resource.Properties, "Engine", "EngineVersion", "DBClusterInstanceClass") + valid_for_iam_engine_and_version_check_edited(resource.Properties, "Engine", "EngineVersion") result := { "documentId": input.document[i].id, @@ -32,7 +32,7 @@ CxPolicy[result] { common_lib.valid_key(resource.Properties, "EnableIAMDatabaseAuthentication") cf_lib.isCloudFormationFalse(resource.Properties.EnableIAMDatabaseAuthentication) - common_lib.valid_for_iam_engine_and_version_check(resource.Properties, "Engine", "EngineVersion", "DBClusterInstanceClass") + valid_for_iam_engine_and_version_check_edited(resource.Properties, "Engine", "EngineVersion") result := { "documentId": input.document[i].id, @@ -46,7 +46,7 @@ CxPolicy[result] { } } -valid_for_iam_engine_and_version_check_edited(resource, engineVar, engineVersionVar, instanceClassVar) { +valid_for_iam_engine_and_version_check_edited(resource, engineVar, engineVersionVar) { key_list := [engineVar, engineVersionVar] contains(lower(resource[engineVar]), "mariadb") supported_versions := {"10.6", "10.11", "11.4"} From 067154eaa0d4d970ff9e377bbea24e92a2422968 Mon Sep 17 00:00:00 2001 From: Ricardo Jesus <219317970+cx-ricardo-jesus@users.noreply.github.com> Date: Wed, 20 Aug 2025 13:55:51 +0100 Subject: [PATCH 08/13] added samples for terraform implementation --- .../metadata.json | 12 ++ .../query.rego | 107 ++++++++++++++++++ .../test/negative1.tf | 15 +++ .../test/positive1.tf | 15 +++ .../test/positive2.tf | 13 +++ .../test/positive_expected_result.json | 14 +++ 6 files changed, 176 insertions(+) create mode 100644 assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/metadata.json create mode 100644 assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/query.rego create mode 100644 assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/negative1.tf create mode 100644 assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive1.tf create mode 100644 assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive2.tf create mode 100644 assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/metadata.json b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/metadata.json new file mode 100644 index 00000000000..60754c006d5 --- /dev/null +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/metadata.json @@ -0,0 +1,12 @@ +{ + "id": "6282794f-def8-4d6f-9df6-289318aa42b8", + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "category": "Access Control", + "descriptionText": "IAM Authentication should be enabled to verify the access of users and applications to your databases by enabling IAM policies and multi-factor authentication. This is a safety measure to ensure the protection of newly created databases without the proper IAM policies or in the change of policies in existing databases.", + "descriptionUrl": "https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-enableiamdatabaseauthentication", + "platform": "", + "descriptionID": "6282794f", + "cloudProvider": "aws", + "cwe": "311" +} \ No newline at end of file diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/query.rego b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/query.rego new file mode 100644 index 00000000000..9877737c6ca --- /dev/null +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/query.rego @@ -0,0 +1,107 @@ +package Cx + +import data.generic.common as common_lib +import data.generic.terraform as tf_lib + +CxPolicy[result] { # iam_database_authentication_enabled not defined for resource + resource := input.document[i].resource.aws_rds_cluster[name] + + not common_lib.valid_key(resource, "iam_database_authentication_enabled") + valid_for_iam_engine_and_version_check_edited(resource, "engine", "engine_version") + + result := { + "documentId": input.document[i].id, + "resourceType": resource.Type, + "resourceName": cf_lib.get_resource_name(resource, name), + "searchKey": sprintf("aws_rds_cluster[%s]", [name]), + "issueType": "MissingAttribute", + "keyExpectedValue": "'iam_database_authentication_enabled' should be set to true", + "keyActualValue": "'iam_database_authentication_enabled' is undefined", + "searchLine": common_lib.build_search_line(["resource", "aws_rds_cluster", name], []), + "remediation": "iam_database_authentication_enabled = true", + "remediationType": "addition", + } +} + +CxPolicy[result] { # iam_database_authentication_enabled set to false for resource + resource := input.document[i].resource.aws_rds_cluster[name] + + resource.iam_database_authentication_enabled == false + valid_for_iam_engine_and_version_check_edited(resource, "engine", "engine_version") + + result := { + "documentId": input.document[i].id, + "resourceType": resource.Type, + "resourceName": cf_lib.get_resource_name(resource, name), + "searchKey": sprintf("aws_rds_cluster[%s]", [name]), + "issueType": "MissingAttribute", + "keyExpectedValue": "'iam_database_authentication_enabled' should be set to true", + "keyActualValue": "'iam_database_authentication_enabled' is undefined", + "searchLine": common_lib.build_search_line(["resource", "aws_rds_cluster", name], []), + "remediation": json.marshal({ + "before": "false", + "after": "true", + }), + "remediationType": "replacement", + } +} + +CxPolicy[result] { # iam_database_authentication_enabled set to false for module + module := input.document[i].module[name] + keyToCheck := common_lib.get_module_equivalent_key("aws", module.source, "aws_rds_cluster", "iam_database_authentication_enabled") + + module[keyToCheck] == false + valid_for_iam_engine_and_version_check_edited(module, "engine", "engine_version") + + result := { + "documentId": input.document[i].id, + "resourceType": "n/a", + "resourceName": "n/a", + "searchKey": sprintf("module[%s].iam_database_authentiaction_enabled", [name]), + "issueType": "IncorrectValue", + "keyExpectedValue": "'iam_database_authentication_enabled' should be set to true", + "keyActualValue": "'iam_database_authentication_enabled' is set to false", + "searchLine": common_lib.build_search_line(["module", name, "iam_database_authentication_enabled"], []), + "remediation": json.marshal({ + "before": "false", + "after": "true", + }), + "remediationType": "replacement", + } +} + +CxPolicy[result] { # iam_database_authentication_enabled not defined for module + module := input.document[i].module[name] + keyToCheck := common_lib.get_module_equivalent_key("aws", module.source, "aws_rds_cluster", "iam_database_authentication_enabled") + + not common_lib.valid_key(module, keyToCheck) + valid_for_iam_engine_and_version_check_edited(module, "engine", "engine_version") + + result := { + "documentId": input.document[i].id, + "resourceType": "n/a", + "resourceName": "n/a", + "searchKey": sprintf("module[%s]", [name]), + "issueType": "MissingAttribute", + "keyExpectedValue": "'iam_database_authentication_enabled' should be set to true", + "keyActualValue": "'iam_database_authentication_enabled' is not defined", + "searchLine": common_lib.build_search_line(["module", name], []), + "remediation": "iam_database_authentication_enabled = true", + "remediationType": "addition", + } +} + +valid_for_iam_engine_and_version_check_edited(resource, engineVar, engineVersionVar) { + key_list := [engineVar, engineVersionVar] + contains(lower(resource[engineVar]), "mariadb") + supported_versions := {"10.6", "10.11", "11.4"} + version_check := {x | x := resource[key_list[_]]; contains(x, supported_versions[_])} + count(version_check) > 0 +} else { + engines_that_support_iam := ["aurora-postgresql", "postgres", "mysql", "mariadb"] + contains(lower(resource[engineVar]), engines_that_support_iam[_]) + not common_lib.valid_key(resource, engineVersionVar) +} else { + engines_that_supports_iam := ["aurora-postgresql", "postgres", "mysql"] + contains(lower(resource[engineVar]), engines_that_supports_iam[_]) +} \ No newline at end of file diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/negative1.tf b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/negative1.tf new file mode 100644 index 00000000000..01df2f931a3 --- /dev/null +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/negative1.tf @@ -0,0 +1,15 @@ +resource "aws_rds_cluster" "negative1" { + cluster_identifier = "example-cluster" + + engine = "aurora-mysql" + engine_version = "8.0.mysql_aurora.3.05.2" + + master_username = "username" + master_password = "password123!" + + iam_database_authentication_enabled = true + + availability_zones = ["us-east-1a", "us-east-1b", "us-east-1c"] + + skip_final_snapshot = true +} diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive1.tf b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive1.tf new file mode 100644 index 00000000000..316213e90ac --- /dev/null +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive1.tf @@ -0,0 +1,15 @@ +resource "aws_rds_cluster" "negative1" { + cluster_identifier = "example-cluster" + + engine = "aurora-mysql" + engine_version = "8.0.mysql_aurora.3.05.2" + + master_username = "username" + master_password = "password123!" + + iam_database_authentication_enabled = false + + availability_zones = ["us-east-1a", "us-east-1b", "us-east-1c"] + + skip_final_snapshot = true +} \ No newline at end of file diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive2.tf b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive2.tf new file mode 100644 index 00000000000..d9c7a98c9e7 --- /dev/null +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive2.tf @@ -0,0 +1,13 @@ +resource "aws_rds_cluster" "negative1" { + cluster_identifier = "example-cluster" + + engine = "aurora-mysql" + engine_version = "8.0.mysql_aurora.3.05.2" + + master_username = "username" + master_password = "password123!" + + availability_zones = ["us-east-1a", "us-east-1b", "us-east-1c"] + + skip_final_snapshot = true +} \ No newline at end of file diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json new file mode 100644 index 00000000000..ab56e8d150e --- /dev/null +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json @@ -0,0 +1,14 @@ +[ + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 0, + "fileName": "positive1.tf" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 0, + "fileName": "positive2.tf" + } +] \ No newline at end of file From e6ba35c7f6804ae29eff85aa3ce71e0690668bf7 Mon Sep 17 00:00:00 2001 From: Ricardo Jesus <219317970+cx-ricardo-jesus@users.noreply.github.com> Date: Wed, 20 Aug 2025 15:35:05 +0100 Subject: [PATCH 09/13] query fully implemented for terraform/aws --- .../metadata.json | 8 +-- .../query.rego | 57 ++----------------- .../test/negative2.tf | 15 +++++ .../test/positive1.tf | 2 +- .../test/positive2.tf | 2 +- .../test/positive3.tf | 10 ++++ .../test/positive4.tf | 10 ++++ .../test/positive5.tf | 11 ++++ .../test/positive6.tf | 10 ++++ .../test/positive_expected_result.json | 28 ++++++++- 10 files changed, 94 insertions(+), 59 deletions(-) create mode 100644 assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/negative2.tf create mode 100644 assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive3.tf create mode 100644 assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive4.tf create mode 100644 assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive5.tf create mode 100644 assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive6.tf diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/metadata.json b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/metadata.json index 60754c006d5..3f39ef00f3e 100644 --- a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/metadata.json +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/metadata.json @@ -1,12 +1,12 @@ { - "id": "6282794f-def8-4d6f-9df6-289318aa42b8", + "id": "228497f6-414f-41c8-9113-f36a2b1b7975", "queryName": "IAM DB Cluster Auth Not Enabled", "severity": "MEDIUM", "category": "Access Control", "descriptionText": "IAM Authentication should be enabled to verify the access of users and applications to your databases by enabling IAM policies and multi-factor authentication. This is a safety measure to ensure the protection of newly created databases without the proper IAM policies or in the change of policies in existing databases.", - "descriptionUrl": "https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-enableiamdatabaseauthentication", - "platform": "", - "descriptionID": "6282794f", + "descriptionUrl": "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster#iam_database_authentication_enabled", + "platform": "Terraform", + "descriptionID": "228497f6", "cloudProvider": "aws", "cwe": "311" } \ No newline at end of file diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/query.rego b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/query.rego index 9877737c6ca..1817ed84c85 100644 --- a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/query.rego +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/query.rego @@ -11,8 +11,8 @@ CxPolicy[result] { # iam_database_authentication_enabled not defined for resourc result := { "documentId": input.document[i].id, - "resourceType": resource.Type, - "resourceName": cf_lib.get_resource_name(resource, name), + "resourceType": "aws_rds_cluster", + "resourceName": tf_lib.get_resource_name(resource, name), "searchKey": sprintf("aws_rds_cluster[%s]", [name]), "issueType": "MissingAttribute", "keyExpectedValue": "'iam_database_authentication_enabled' should be set to true", @@ -31,13 +31,13 @@ CxPolicy[result] { # iam_database_authentication_enabled set to false for resour result := { "documentId": input.document[i].id, - "resourceType": resource.Type, - "resourceName": cf_lib.get_resource_name(resource, name), - "searchKey": sprintf("aws_rds_cluster[%s]", [name]), + "resourceType": "aws_rds_cluster", + "resourceName": tf_lib.get_resource_name(resource, name), + "searchKey": sprintf("aws_rds_cluster[%s].iam_database_authentication_enabled", [name]), "issueType": "MissingAttribute", "keyExpectedValue": "'iam_database_authentication_enabled' should be set to true", "keyActualValue": "'iam_database_authentication_enabled' is undefined", - "searchLine": common_lib.build_search_line(["resource", "aws_rds_cluster", name], []), + "searchLine": common_lib.build_search_line(["resource", "aws_rds_cluster", name, "iam_database_authentication_enabled"], []), "remediation": json.marshal({ "before": "false", "after": "true", @@ -46,51 +46,6 @@ CxPolicy[result] { # iam_database_authentication_enabled set to false for resour } } -CxPolicy[result] { # iam_database_authentication_enabled set to false for module - module := input.document[i].module[name] - keyToCheck := common_lib.get_module_equivalent_key("aws", module.source, "aws_rds_cluster", "iam_database_authentication_enabled") - - module[keyToCheck] == false - valid_for_iam_engine_and_version_check_edited(module, "engine", "engine_version") - - result := { - "documentId": input.document[i].id, - "resourceType": "n/a", - "resourceName": "n/a", - "searchKey": sprintf("module[%s].iam_database_authentiaction_enabled", [name]), - "issueType": "IncorrectValue", - "keyExpectedValue": "'iam_database_authentication_enabled' should be set to true", - "keyActualValue": "'iam_database_authentication_enabled' is set to false", - "searchLine": common_lib.build_search_line(["module", name, "iam_database_authentication_enabled"], []), - "remediation": json.marshal({ - "before": "false", - "after": "true", - }), - "remediationType": "replacement", - } -} - -CxPolicy[result] { # iam_database_authentication_enabled not defined for module - module := input.document[i].module[name] - keyToCheck := common_lib.get_module_equivalent_key("aws", module.source, "aws_rds_cluster", "iam_database_authentication_enabled") - - not common_lib.valid_key(module, keyToCheck) - valid_for_iam_engine_and_version_check_edited(module, "engine", "engine_version") - - result := { - "documentId": input.document[i].id, - "resourceType": "n/a", - "resourceName": "n/a", - "searchKey": sprintf("module[%s]", [name]), - "issueType": "MissingAttribute", - "keyExpectedValue": "'iam_database_authentication_enabled' should be set to true", - "keyActualValue": "'iam_database_authentication_enabled' is not defined", - "searchLine": common_lib.build_search_line(["module", name], []), - "remediation": "iam_database_authentication_enabled = true", - "remediationType": "addition", - } -} - valid_for_iam_engine_and_version_check_edited(resource, engineVar, engineVersionVar) { key_list := [engineVar, engineVersionVar] contains(lower(resource[engineVar]), "mariadb") diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/negative2.tf b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/negative2.tf new file mode 100644 index 00000000000..e034b795778 --- /dev/null +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/negative2.tf @@ -0,0 +1,15 @@ +resource "aws_rds_cluster" "negative1" { + cluster_identifier = "example-cluster" + + engine = "mariadb" + engine_version = "10.5" + + master_username = "username" + master_password = "password123!" + + iam_database_authentication_enabled = false + + availability_zones = ["us-east-1a", "us-east-1b", "us-east-1c"] + + skip_final_snapshot = true +} diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive1.tf b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive1.tf index 316213e90ac..f57f890e939 100644 --- a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive1.tf +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive1.tf @@ -1,4 +1,4 @@ -resource "aws_rds_cluster" "negative1" { +resource "aws_rds_cluster" "positive1" { cluster_identifier = "example-cluster" engine = "aurora-mysql" diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive2.tf b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive2.tf index d9c7a98c9e7..19367fa66e5 100644 --- a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive2.tf +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive2.tf @@ -1,4 +1,4 @@ -resource "aws_rds_cluster" "negative1" { +resource "aws_rds_cluster" "positive2" { cluster_identifier = "example-cluster" engine = "aurora-mysql" diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive3.tf b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive3.tf new file mode 100644 index 00000000000..78f9e8fec7e --- /dev/null +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive3.tf @@ -0,0 +1,10 @@ +resource "aws_rds_cluster" "positive3" { + cluster_identifier = "mysql-no-version" + engine = "mysql" + + master_username = "user" + master_password = "pass1234!" + + # intentionally omit iam_database_authentication_enabled + skip_final_snapshot = true +} diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive4.tf b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive4.tf new file mode 100644 index 00000000000..ebfa788a38b --- /dev/null +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive4.tf @@ -0,0 +1,10 @@ +resource "aws_rds_cluster" "positive4" { + cluster_identifier = "mysql-no-version" + engine = "mysql" + + master_username = "user" + master_password = "pass1234!" + + iam_database_authentication_enabled = false + skip_final_snapshot = true +} diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive5.tf b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive5.tf new file mode 100644 index 00000000000..355c57e6f0b --- /dev/null +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive5.tf @@ -0,0 +1,11 @@ +resource "aws_rds_cluster" "positive5" { + cluster_identifier = "mariadb-with-version" + engine = "mariadb" + engine_version = "10.11" + + master_username = "user" + master_password = "pass1234!" + + iam_database_authentication_enabled = false + skip_final_snapshot = true +} diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive6.tf b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive6.tf new file mode 100644 index 00000000000..bc5fe200979 --- /dev/null +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive6.tf @@ -0,0 +1,10 @@ +resource "aws_rds_cluster" "positive6" { + cluster_identifier = "mariadb-with-version" + engine = "mariadb" + engine_version = "10.11" + + master_username = "user" + master_password = "pass1234!" + + skip_final_snapshot = true +} diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json index ab56e8d150e..81235fc85a7 100644 --- a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json @@ -2,13 +2,37 @@ { "queryName": "IAM DB Cluster Auth Not Enabled", "severity": "MEDIUM", - "line": 0, + "line": 10, "fileName": "positive1.tf" }, { "queryName": "IAM DB Cluster Auth Not Enabled", "severity": "MEDIUM", - "line": 0, + "line": 1, "fileName": "positive2.tf" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 1, + "fileName": "positive3.tf" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 8, + "fileName": "positive4.tf" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 9, + "fileName": "positive5.tf" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 1, + "fileName": "positive6.tf" } ] \ No newline at end of file From 76d798bc1f2850da02d01b0a3afee47828d4fe0a Mon Sep 17 00:00:00 2001 From: Ricardo Jesus <219317970+cx-ricardo-jesus@users.noreply.github.com> Date: Wed, 20 Aug 2025 16:09:39 +0100 Subject: [PATCH 10/13] added extra samples for cloudFormation --- .../test/negative5.yaml | 15 ++++ .../test/negative6.json | 27 +++++++ .../test/negative7.yaml | 15 ++++ .../test/negative8.json | 27 +++++++ .../test/positive10.json | 26 +++++++ .../test/positive11.yaml | 13 ++++ .../test/positive12.json | 25 +++++++ .../test/positive13.yaml | 14 ++++ .../test/positive14.json | 26 +++++++ .../test/positive15.yaml | 14 ++++ .../test/positive16.json | 26 +++++++ .../test/positive17.yaml | 12 ++++ .../test/positive18.json | 24 +++++++ .../test/positive7.yaml | 14 ++++ .../test/positive8.json | 26 +++++++ .../test/positive9.yaml | 14 ++++ .../test/positive_expected_result.json | 72 +++++++++++++++++++ 17 files changed, 390 insertions(+) create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative5.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative6.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative7.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative8.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive10.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive11.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive12.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive13.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive14.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive15.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive16.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive17.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive18.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive7.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive8.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive9.yaml diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative5.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative5.yaml new file mode 100644 index 00000000000..240630b32af --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative5.yaml @@ -0,0 +1,15 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + sample: + Type: 'AWS::RDS::DBCluster' + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: true + DBClusterIdentifier: !Ref SourceDBInstanceIdentifier + Engine: mariadb + EngineVersion: '10.5' + DBClusterParameterGroupName: default.aurora-postgresql10 + EnableCloudwatchLogsExports: + - postgresql + EnableIAMDatabaseAuthentication: true diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative6.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative6.json new file mode 100644 index 00000000000..b213fc0c3ef --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative6.json @@ -0,0 +1,27 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "sample": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": true, + "DBClusterIdentifier": { + "Ref": "SourceDBInstanceIdentifier" + }, + "Engine": "mariadb", + "EngineVersion": "10.5", + "DBClusterParameterGroupName": "default.aurora-postgresql10", + "EnableCloudwatchLogsExports": [ + "postgresql" + ], + "EnableIAMDatabaseAuthentication": true + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative7.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative7.yaml new file mode 100644 index 00000000000..4443cc481be --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative7.yaml @@ -0,0 +1,15 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + sample: + Type: 'AWS::RDS::DBCluster' + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: "true" + DBClusterIdentifier: !Ref SourceDBInstanceIdentifier + Engine: mariadb + EngineVersion: '10.5' + DBClusterParameterGroupName: default.aurora-postgresql10 + EnableCloudwatchLogsExports: + - postgresql + EnableIAMDatabaseAuthentication: "true" diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative8.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative8.json new file mode 100644 index 00000000000..4058555ee30 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative8.json @@ -0,0 +1,27 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "sample": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": "true", + "DBClusterIdentifier": { + "Ref": "SourceDBInstanceIdentifier" + }, + "Engine": "mariadb", + "EngineVersion": "10.5", + "DBClusterParameterGroupName": "default.aurora-postgresql10", + "EnableCloudwatchLogsExports": [ + "postgresql" + ], + "EnableIAMDatabaseAuthentication": "true" + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive10.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive10.json new file mode 100644 index 00000000000..727041c049b --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive10.json @@ -0,0 +1,26 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "sample": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": true, + "DBClusterIdentifier": { + "Ref": "SourceDBInstanceIdentifier" + }, + "Engine": "mysql", + "DBClusterParameterGroupName": "default.mysql10", + "EnableCloudwatchLogsExports": [ + "mysql" + ], + "EnableIAMDatabaseAuthentication": "false" + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive11.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive11.yaml new file mode 100644 index 00000000000..7f0b2d611a8 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive11.yaml @@ -0,0 +1,13 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + sample: + Type: 'AWS::RDS::DBCluster' + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: true + DBClusterIdentifier: !Ref SourceDBInstanceIdentifier + Engine: mysql + DBClusterParameterGroupName: default.mysql10 + EnableCloudwatchLogsExports: + - mysql diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive12.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive12.json new file mode 100644 index 00000000000..944e8ec7f35 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive12.json @@ -0,0 +1,25 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "sample": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": true, + "DBClusterIdentifier": { + "Ref": "SourceDBInstanceIdentifier" + }, + "Engine": "mysql", + "DBClusterParameterGroupName": "default.mysql10", + "EnableCloudwatchLogsExports": [ + "mysql" + ] + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive13.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive13.yaml new file mode 100644 index 00000000000..d6e4c3793ae --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive13.yaml @@ -0,0 +1,14 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + sample: + Type: 'AWS::RDS::DBCluster' + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: true + DBClusterIdentifier: !Ref SourceDBInstanceIdentifier + Engine: mariadb + DBClusterParameterGroupName: default.mariadb + EnableCloudwatchLogsExports: + - mariadb + EnableIAMDatabaseAuthentication: false diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive14.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive14.json new file mode 100644 index 00000000000..29b794c8478 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive14.json @@ -0,0 +1,26 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "sample": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": true, + "DBClusterIdentifier": { + "Ref": "SourceDBInstanceIdentifier" + }, + "Engine": "mariadb", + "DBClusterParameterGroupName": "default.mariadb", + "EnableCloudwatchLogsExports": [ + "mariadb" + ], + "EnableIAMDatabaseAuthentication": false + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive15.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive15.yaml new file mode 100644 index 00000000000..cb041703341 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive15.yaml @@ -0,0 +1,14 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + sample: + Type: 'AWS::RDS::DBCluster' + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: "true" + DBClusterIdentifier: !Ref SourceDBInstanceIdentifier + Engine: mariadb + DBClusterParameterGroupName: default.mariadb + EnableCloudwatchLogsExports: + - mariadb + EnableIAMDatabaseAuthentication: "false" diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive16.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive16.json new file mode 100644 index 00000000000..fb688d7a9f7 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive16.json @@ -0,0 +1,26 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "sample": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": "true", + "DBClusterIdentifier": { + "Ref": "SourceDBInstanceIdentifier" + }, + "Engine": "mariadb", + "DBClusterParameterGroupName": "default.mariadb", + "EnableCloudwatchLogsExports": [ + "mariadb" + ], + "EnableIAMDatabaseAuthentication": "false" + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive17.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive17.yaml new file mode 100644 index 00000000000..901d7fb8cc1 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive17.yaml @@ -0,0 +1,12 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + sample: + Type: 'AWS::RDS::DBCluster' + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + DBClusterIdentifier: !Ref SourceDBInstanceIdentifier + Engine: mariadb + DBClusterParameterGroupName: default.mariadb + EnableCloudwatchLogsExports: + - mariadb diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive18.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive18.json new file mode 100644 index 00000000000..1f644ea442a --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive18.json @@ -0,0 +1,24 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "sample": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "DBClusterIdentifier": { + "Ref": "SourceDBInstanceIdentifier" + }, + "Engine": "mariadb", + "DBClusterParameterGroupName": "default.mariadb", + "EnableCloudwatchLogsExports": [ + "mariadb" + ] + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive7.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive7.yaml new file mode 100644 index 00000000000..6f167940a46 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive7.yaml @@ -0,0 +1,14 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + sample: + Type: 'AWS::RDS::DBCluster' + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: true + DBClusterIdentifier: !Ref SourceDBInstanceIdentifier + Engine: mysql + DBClusterParameterGroupName: default.mysql10 + EnableCloudwatchLogsExports: + - mysql + EnableIAMDatabaseAuthentication: false diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive8.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive8.json new file mode 100644 index 00000000000..db8b47def9d --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive8.json @@ -0,0 +1,26 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "sample": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": true, + "DBClusterIdentifier": { + "Ref": "SourceDBInstanceIdentifier" + }, + "Engine": "mysql", + "DBClusterParameterGroupName": "default.mysql10", + "EnableCloudwatchLogsExports": [ + "mysql" + ], + "EnableIAMDatabaseAuthentication": false + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive9.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive9.yaml new file mode 100644 index 00000000000..5a0fe4e16f6 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive9.yaml @@ -0,0 +1,14 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + sample: + Type: 'AWS::RDS::DBCluster' + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: true + DBClusterIdentifier: !Ref SourceDBInstanceIdentifier + Engine: mysql + DBClusterParameterGroupName: default.mysql10 + EnableCloudwatchLogsExports: + - mysql + EnableIAMDatabaseAuthentication: "false" diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json index 09bd61d6f77..42ce5e76de2 100644 --- a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json @@ -34,5 +34,77 @@ "severity": "MEDIUM", "line": 21, "fileName": "positive6.json" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 14, + "fileName": "positive7.yaml" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 22, + "fileName": "positive8.json" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 14, + "fileName": "positive9.yaml" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 22, + "fileName": "positive10.json" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 5, + "fileName": "positive11.yaml" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 6, + "fileName": "positive12.json" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 14, + "fileName": "positive13.yaml" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 22, + "fileName": "positive14.json" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 14, + "fileName": "positive15.yaml" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 22, + "fileName": "positive16.json" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 5, + "fileName": "positive17.yaml" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 6, + "fileName": "positive18.json" } ] \ No newline at end of file From e1d02a04ec575c91e7385f97419c4329b4aa1cd8 Mon Sep 17 00:00:00 2001 From: Ricardo Jesus <219317970+cx-ricardo-jesus@users.noreply.github.com> Date: Wed, 20 Aug 2025 16:22:19 +0100 Subject: [PATCH 11/13] fixed valid_for_iam_engine_and_version_check function on common_lib --- assets/libraries/common.rego | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assets/libraries/common.rego b/assets/libraries/common.rego index c0ebd0db02e..ae49634f0b2 100644 --- a/assets/libraries/common.rego +++ b/assets/libraries/common.rego @@ -581,7 +581,8 @@ weakCipher(aux) { valid_for_iam_engine_and_version_check(resource, engineVar, engineVersionVar, instanceClassVar) { key_list := [engineVar, engineVersionVar] contains(lower(resource[engineVar]), "mariadb") - version_check := {x | x := resource[key_list[_]]; contains(x, "10.6")} + supported_versions := {"10.6", "10.11", "11.4"} + version_check := {x | x := resource[key_list[_]]; contains(x, supported_versions[_])} count(version_check) > 0 } else { engines_that_supports_iam := ["aurora-postgresql", "postgres", "mysql", "mariadb"] From d9cd66eb92322b34030ee4cea7faf4a005e8755f Mon Sep 17 00:00:00 2001 From: Ricardo Jesus <219317970+cx-ricardo-jesus@users.noreply.github.com> Date: Fri, 22 Aug 2025 15:41:36 +0100 Subject: [PATCH 12/13] fixed typo and samples added for terraform query --- .../query.rego | 2 +- .../test/negative3.tf | 15 ++++++++++++ .../test/positive10.tf | 12 ++++++++++ .../test/positive7.tf | 15 ++++++++++++ .../test/positive8.tf | 13 ++++++++++ .../test/positive9.tf | 14 +++++++++++ .../test/positive_expected_result.json | 24 +++++++++++++++++++ 7 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/negative3.tf create mode 100644 assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive10.tf create mode 100644 assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive7.tf create mode 100644 assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive8.tf create mode 100644 assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive9.tf diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/query.rego b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/query.rego index 1817ed84c85..8d14030aa7c 100644 --- a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/query.rego +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/query.rego @@ -36,7 +36,7 @@ CxPolicy[result] { # iam_database_authentication_enabled set to false for resour "searchKey": sprintf("aws_rds_cluster[%s].iam_database_authentication_enabled", [name]), "issueType": "MissingAttribute", "keyExpectedValue": "'iam_database_authentication_enabled' should be set to true", - "keyActualValue": "'iam_database_authentication_enabled' is undefined", + "keyActualValue": "'iam_database_authentication_enabled' is defined to false", "searchLine": common_lib.build_search_line(["resource", "aws_rds_cluster", name, "iam_database_authentication_enabled"], []), "remediation": json.marshal({ "before": "false", diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/negative3.tf b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/negative3.tf new file mode 100644 index 00000000000..e70cc341893 --- /dev/null +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/negative3.tf @@ -0,0 +1,15 @@ +resource "aws_rds_cluster" "example_postgres" { + cluster_identifier = "example-postgres-cluster" + + engine = "postgres" + engine_version = "15.5" + + master_username = "dbadmin" + master_password = "StrongPassword123!" + + iam_database_authentication_enabled = true + + availability_zones = ["us-east-1a", "us-east-1b", "us-east-1c"] + + skip_final_snapshot = true +} diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive10.tf b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive10.tf new file mode 100644 index 00000000000..c97e7e1b5c3 --- /dev/null +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive10.tf @@ -0,0 +1,12 @@ +resource "aws_rds_cluster" "example_postgres" { + cluster_identifier = "example-postgres-cluster" + + engine = "postgres" + + master_username = "dbadmin" + master_password = "StrongPassword123!" + + availability_zones = ["us-east-1a", "us-east-1b", "us-east-1c"] + + skip_final_snapshot = true +} diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive7.tf b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive7.tf new file mode 100644 index 00000000000..51420201661 --- /dev/null +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive7.tf @@ -0,0 +1,15 @@ +resource "aws_rds_cluster" "example_postgres" { + cluster_identifier = "example-postgres-cluster" + + engine = "postgres" + engine_version = "15.5" + + master_username = "dbadmin" + master_password = "StrongPassword123!" + + iam_database_authentication_enabled = false + + availability_zones = ["us-east-1a", "us-east-1b", "us-east-1c"] + + skip_final_snapshot = true +} diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive8.tf b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive8.tf new file mode 100644 index 00000000000..38d88f99059 --- /dev/null +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive8.tf @@ -0,0 +1,13 @@ +resource "aws_rds_cluster" "example_postgres" { + cluster_identifier = "example-postgres-cluster" + + engine = "postgres" + engine_version = "15.5" + + master_username = "dbadmin" + master_password = "StrongPassword123!" + + availability_zones = ["us-east-1a", "us-east-1b", "us-east-1c"] + + skip_final_snapshot = true +} diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive9.tf b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive9.tf new file mode 100644 index 00000000000..a486450d8f2 --- /dev/null +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive9.tf @@ -0,0 +1,14 @@ +resource "aws_rds_cluster" "example_postgres" { + cluster_identifier = "example-postgres-cluster" + + engine = "postgres" + + master_username = "dbadmin" + master_password = "StrongPassword123!" + + iam_database_authentication_enabled = false + + availability_zones = ["us-east-1a", "us-east-1b", "us-east-1c"] + + skip_final_snapshot = true +} diff --git a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json index 81235fc85a7..c73b9e069f2 100644 --- a/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json +++ b/assets/queries/terraform/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json @@ -34,5 +34,29 @@ "severity": "MEDIUM", "line": 1, "fileName": "positive6.tf" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 10, + "fileName": "positive7.tf" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 1, + "fileName": "positive8.tf" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 9, + "fileName": "positive9.tf" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 1, + "fileName": "positive10.tf" } ] \ No newline at end of file From 3e75e15e1f08703942252651877806b817f9156b Mon Sep 17 00:00:00 2001 From: Ricardo Jesus <219317970+cx-ricardo-jesus@users.noreply.github.com> Date: Fri, 22 Aug 2025 16:22:00 +0100 Subject: [PATCH 13/13] added samples for CloudFormation --- .../test/negative10.json | 25 +++++++ .../test/negative11.yaml | 15 ++++ .../test/negative12.json | 25 +++++++ .../test/negative13.yaml | 14 ++++ .../test/negative14.json | 24 +++++++ .../test/negative15.yaml | 14 ++++ .../test/negative16.json | 24 +++++++ .../test/negative9.yaml | 15 ++++ .../test/positive19.yaml | 14 ++++ .../test/positive20.json | 24 +++++++ .../test/positive21.yaml | 13 ++++ .../test/positive22.json | 23 ++++++ .../test/positive23.yaml | 15 ++++ .../test/positive24.json | 25 +++++++ .../test/positive25.yaml | 15 ++++ .../test/positive26.json | 25 +++++++ .../test/positive27.yaml | 15 ++++ .../test/positive28.json | 24 +++++++ .../test/positive29.yaml | 14 ++++ .../test/positive30.json | 24 +++++++ .../test/positive_expected_result.json | 72 +++++++++++++++++++ 21 files changed, 459 insertions(+) create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative10.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative11.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative12.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative13.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative14.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative15.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative16.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative9.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive19.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive20.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive21.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive22.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive23.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive24.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive25.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive26.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive27.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive28.json create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive29.yaml create mode 100644 assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive30.json diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative10.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative10.json new file mode 100644 index 00000000000..918016b13fe --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative10.json @@ -0,0 +1,25 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "PostgresDBCluster": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": true, + "DBClusterIdentifier": "postgres-db-cluster", + "Engine": "postgres", + "EngineVersion": "15.5", + "DBClusterParameterGroupName": "default.postgres15", + "EnableCloudwatchLogsExports": [ + "postgresql" + ], + "EnableIAMDatabaseAuthentication": true + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative11.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative11.yaml new file mode 100644 index 00000000000..2a66ab8d405 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative11.yaml @@ -0,0 +1,15 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + PostgresDBCluster: + Type: "AWS::RDS::DBCluster" + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: "true" + DBClusterIdentifier: postgres-db-cluster + Engine: postgres + EngineVersion: "15.5" + DBClusterParameterGroupName: default.postgres15 + EnableCloudwatchLogsExports: + - postgresql + EnableIAMDatabaseAuthentication: "true" diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative12.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative12.json new file mode 100644 index 00000000000..f5786c861c0 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative12.json @@ -0,0 +1,25 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "PostgresDBCluster": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": "true", + "DBClusterIdentifier": "postgres-db-cluster", + "Engine": "postgres", + "EngineVersion": "15.5", + "DBClusterParameterGroupName": "default.postgres15", + "EnableCloudwatchLogsExports": [ + "postgresql" + ], + "EnableIAMDatabaseAuthentication": "true" + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative13.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative13.yaml new file mode 100644 index 00000000000..3f7daad098d --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative13.yaml @@ -0,0 +1,14 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + PostgresDBCluster: + Type: "AWS::RDS::DBCluster" + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: true + DBClusterIdentifier: postgres-db-cluster + Engine: postgres + DBClusterParameterGroupName: default.postgres15 + EnableCloudwatchLogsExports: + - postgresql + EnableIAMDatabaseAuthentication: true diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative14.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative14.json new file mode 100644 index 00000000000..37124dd0bd6 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative14.json @@ -0,0 +1,24 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "PostgresDBCluster": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": true, + "DBClusterIdentifier": "postgres-db-cluster", + "Engine": "postgres", + "DBClusterParameterGroupName": "default.postgres15", + "EnableCloudwatchLogsExports": [ + "postgresql" + ], + "EnableIAMDatabaseAuthentication": true + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative15.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative15.yaml new file mode 100644 index 00000000000..e80e25375f5 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative15.yaml @@ -0,0 +1,14 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + PostgresDBCluster: + Type: "AWS::RDS::DBCluster" + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: "true" + DBClusterIdentifier: postgres-db-cluster + Engine: postgres + DBClusterParameterGroupName: default.postgres15 + EnableCloudwatchLogsExports: + - postgresql + EnableIAMDatabaseAuthentication: "true" diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative16.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative16.json new file mode 100644 index 00000000000..a5713dee791 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative16.json @@ -0,0 +1,24 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "PostgresDBCluster": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": "true", + "DBClusterIdentifier": "postgres-db-cluster", + "Engine": "postgres", + "DBClusterParameterGroupName": "default.postgres15", + "EnableCloudwatchLogsExports": [ + "postgresql" + ], + "EnableIAMDatabaseAuthentication": "true" + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative9.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative9.yaml new file mode 100644 index 00000000000..5395496ab27 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/negative9.yaml @@ -0,0 +1,15 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + PostgresDBCluster: + Type: "AWS::RDS::DBCluster" + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: true + DBClusterIdentifier: postgres-db-cluster + Engine: postgres + EngineVersion: "15.5" + DBClusterParameterGroupName: default.postgres15 + EnableCloudwatchLogsExports: + - postgresql + EnableIAMDatabaseAuthentication: true diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive19.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive19.yaml new file mode 100644 index 00000000000..e38045f656d --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive19.yaml @@ -0,0 +1,14 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + PostgresDBCluster: + Type: "AWS::RDS::DBCluster" + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: true + DBClusterIdentifier: postgres-db-cluster + Engine: postgres + EngineVersion: "15.5" + DBClusterParameterGroupName: default.postgres15 + EnableCloudwatchLogsExports: + - postgresql diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive20.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive20.json new file mode 100644 index 00000000000..1d704744207 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive20.json @@ -0,0 +1,24 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "PostgresDBCluster": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": true, + "DBClusterIdentifier": "postgres-db-cluster", + "Engine": "postgres", + "EngineVersion": "15.5", + "DBClusterParameterGroupName": "default.postgres15", + "EnableCloudwatchLogsExports": [ + "postgresql" + ] + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive21.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive21.yaml new file mode 100644 index 00000000000..09f58f2e553 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive21.yaml @@ -0,0 +1,13 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + PostgresDBCluster: + Type: "AWS::RDS::DBCluster" + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: true + DBClusterIdentifier: postgres-db-cluster + Engine: postgres + DBClusterParameterGroupName: default.postgres15 + EnableCloudwatchLogsExports: + - postgresql \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive22.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive22.json new file mode 100644 index 00000000000..4b9c34acc4e --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive22.json @@ -0,0 +1,23 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "PostgresDBCluster": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": true, + "DBClusterIdentifier": "postgres-db-cluster", + "Engine": "postgres", + "DBClusterParameterGroupName": "default.postgres15", + "EnableCloudwatchLogsExports": [ + "postgresql" + ] + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive23.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive23.yaml new file mode 100644 index 00000000000..d3bbde28103 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive23.yaml @@ -0,0 +1,15 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + PostgresDBCluster: + Type: "AWS::RDS::DBCluster" + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: true + DBClusterIdentifier: postgres-db-cluster + Engine: postgres + EngineVersion: "15.5" + DBClusterParameterGroupName: default.postgres15 + EnableCloudwatchLogsExports: + - postgresql + EnableIAMDatabaseAuthentication: false diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive24.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive24.json new file mode 100644 index 00000000000..558aa481005 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive24.json @@ -0,0 +1,25 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "PostgresDBCluster": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": true, + "DBClusterIdentifier": "postgres-db-cluster", + "Engine": "postgres", + "EngineVersion": "15.5", + "DBClusterParameterGroupName": "default.postgres15", + "EnableCloudwatchLogsExports": [ + "postgresql" + ], + "EnableIAMDatabaseAuthentication": false + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive25.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive25.yaml new file mode 100644 index 00000000000..51fd1f398d8 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive25.yaml @@ -0,0 +1,15 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + PostgresDBCluster: + Type: "AWS::RDS::DBCluster" + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: true + DBClusterIdentifier: postgres-db-cluster + Engine: postgres + EngineVersion: "15.5" + DBClusterParameterGroupName: default.postgres15 + EnableCloudwatchLogsExports: + - postgresql + EnableIAMDatabaseAuthentication: "false" diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive26.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive26.json new file mode 100644 index 00000000000..17d804383dd --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive26.json @@ -0,0 +1,25 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "PostgresDBCluster": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": true, + "DBClusterIdentifier": "postgres-db-cluster", + "Engine": "postgres", + "EngineVersion": "15.5", + "DBClusterParameterGroupName": "default.postgres15", + "EnableCloudwatchLogsExports": [ + "postgresql" + ], + "EnableIAMDatabaseAuthentication": "false" + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive27.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive27.yaml new file mode 100644 index 00000000000..62de69a4aaa --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive27.yaml @@ -0,0 +1,15 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + PostgresDBCluster: + Type: "AWS::RDS::DBCluster" + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: true + DBClusterIdentifier: postgres-db-cluster + Engine: postgres + + DBClusterParameterGroupName: default.postgres15 + EnableCloudwatchLogsExports: + - postgresql + EnableIAMDatabaseAuthentication: false \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive28.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive28.json new file mode 100644 index 00000000000..26abd3fd261 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive28.json @@ -0,0 +1,24 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "PostgresDBCluster": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": true, + "DBClusterIdentifier": "postgres-db-cluster", + "Engine": "postgres", + "DBClusterParameterGroupName": "default.postgres15", + "EnableCloudwatchLogsExports": [ + "postgresql" + ], + "EnableIAMDatabaseAuthentication": false + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive29.yaml b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive29.yaml new file mode 100644 index 00000000000..d3e6c0eaec6 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive29.yaml @@ -0,0 +1,14 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + PostgresDBCluster: + Type: "AWS::RDS::DBCluster" + Properties: + MasterUsername: !Ref DBUsername + MasterUserPassword: !Ref DBPassword + StorageEncrypted: true + DBClusterIdentifier: postgres-db-cluster + Engine: postgres + DBClusterParameterGroupName: default.postgres15 + EnableCloudwatchLogsExports: + - postgresql + EnableIAMDatabaseAuthentication: "false" \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive30.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive30.json new file mode 100644 index 00000000000..141d88f2687 --- /dev/null +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive30.json @@ -0,0 +1,24 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "PostgresDBCluster": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "MasterUsername": { + "Ref": "DBUsername" + }, + "MasterUserPassword": { + "Ref": "DBPassword" + }, + "StorageEncrypted": true, + "DBClusterIdentifier": "postgres-db-cluster", + "Engine": "postgres", + "DBClusterParameterGroupName": "default.postgres15", + "EnableCloudwatchLogsExports": [ + "postgresql" + ], + "EnableIAMDatabaseAuthentication": "false" + } + } + } +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json index 42ce5e76de2..08543c17b55 100644 --- a/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/iam_db_cluster_auth_not_enabled/test/positive_expected_result.json @@ -106,5 +106,77 @@ "severity": "MEDIUM", "line": 6, "fileName": "positive18.json" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 5, + "fileName": "positive19.yaml" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 6, + "fileName": "positive20.json" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 5, + "fileName": "positive21.yaml" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 6, + "fileName": "positive22.json" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 15, + "fileName": "positive23.yaml" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 21, + "fileName": "positive24.json" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 15, + "fileName": "positive25.yaml" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 21, + "fileName": "positive26.json" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 15, + "fileName": "positive27.yaml" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 20, + "fileName": "positive28.json" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 14, + "fileName": "positive29.yaml" + }, + { + "queryName": "IAM DB Cluster Auth Not Enabled", + "severity": "MEDIUM", + "line": 20, + "fileName": "positive30.json" } ] \ No newline at end of file