From 27570becaa3b9f1d8020ff7be522e78e4b29fc98 Mon Sep 17 00:00:00 2001 From: Rabea Zreik <47931006+RabeaZr@users.noreply.github.com> Date: Thu, 9 Nov 2023 14:42:39 +0200 Subject: [PATCH] feat(sast): Python cdk policies batch 2 (#5725) * 5 policies added * name change * 16 more policies * 3 more policies * fixes * fixes * fixes * new policies * new policies * blank lines deleted * new policy * fix secrets * add test * blanks * blanks * fixes * typo * fix * fix ids * added tests * fixes * improvements * improvements --------- Co-authored-by: pazbechor --- .../APIGatewayAccessLogging/fail__2__.py | 66 +++++++++ .../python/APIGatewayAccessLogging/pass.py | 70 ++++++++++ .../AmazonMQBrokerPublicAccess/fail__1__.py | 21 +++ .../python/AmazonMQBrokerPublicAccess/pass.py | 21 +++ .../python/AppSyncFieldLevelLogs/fail__1__.py | 24 ++++ .../src/python/AppSyncFieldLevelLogs/pass.py | 25 ++++ .../src/python/AppSyncLogging/fail__1__.py | 24 ++++ .../src/python/AppSyncLogging/pass.py | 25 ++++ .../AthenaWorkgroupConfiguration/fail__1__.py | 28 ++++ .../AthenaWorkgroupConfiguration/pass.py | 28 ++++ .../CloudTrailLogValidation/fail__1__.py | 24 ++++ .../python/CloudTrailLogValidation/pass.py | 24 ++++ .../src/python/DocDBAuditLogs/fail__1__.py | 22 +++ .../src/python/DocDBAuditLogs/pass.py | 22 +++ .../python/EFSEncryptionEnabled/fail__1__.py | 18 +++ .../src/python/EFSEncryptionEnabled/pass.py | 19 +++ .../fail__1__.py | 26 ++++ .../pass.py | 27 ++++ .../fail__1__.py | 26 ++++ .../ElasticsearchDomainEnforceHTTPS/pass.py | 33 +++++ .../fail__1__.py | 27 ++++ .../IAMPolicyAttachedToGroupOrRoles/pass.py | 26 ++++ .../KinesisStreamEncryptionType/fail__1__.py | 23 ++++ .../KinesisStreamEncryptionType/pass.py | 23 ++++ .../RDSEnhancedMonitorEnabled/fail__1__.py | 28 ++++ .../python/RDSEnhancedMonitorEnabled/pass.py | 29 ++++ .../python/RDSPubliclyAccessible/fail__1__.py | 29 ++++ .../src/python/RDSPubliclyAccessible/pass.py | 29 ++++ .../fail__1__.py | 22 +++ .../RedshiftClusterPubliclyAccessible/pass.py | 22 +++ .../src/python/WAFEnabled/fail__1__.py | 3 +- cdk_integration_tests/test_checks_python.py | 128 +++++++++++++----- cdk_integration_tests/utils.py | 13 +- .../python/APIGatewayAccessLogging.yaml | 27 ++++ .../python/AmazonMQBrokerPublicAccess.yaml | 11 ++ .../checks/python/AppSyncFieldLevelLogs.yaml | 22 +++ checkov/cdk/checks/python/AppSyncLogging.yaml | 17 +++ .../python/AthenaWorkgroupConfiguration.yaml | 17 +++ .../python/CloudTrailLogValidation.yaml | 13 ++ checkov/cdk/checks/python/DocDBAuditLogs.yaml | 13 ++ .../checks/python/EFSEncryptionEnabled.yaml | 13 ++ ...cacheReplicationGroupEncryptionAtRest.yaml | 13 ++ .../ElasticsearchDomainEnforceHTTPS.yaml | 17 +++ .../IAMPolicyAttachedToGroupOrRoles.yaml | 17 +++ .../python/KinesisStreamEncryptionType.yaml | 14 ++ .../python/RDSEnhancedMonitorEnabled.yaml | 15 ++ .../checks/python/RDSPubliclyAccessible.yaml | 11 ++ .../RedshiftClusterPubliclyAccessible.yaml | 11 ++ 48 files changed, 1171 insertions(+), 35 deletions(-) create mode 100644 cdk_integration_tests/src/python/APIGatewayAccessLogging/fail__2__.py create mode 100644 cdk_integration_tests/src/python/APIGatewayAccessLogging/pass.py create mode 100644 cdk_integration_tests/src/python/AmazonMQBrokerPublicAccess/fail__1__.py create mode 100644 cdk_integration_tests/src/python/AmazonMQBrokerPublicAccess/pass.py create mode 100644 cdk_integration_tests/src/python/AppSyncFieldLevelLogs/fail__1__.py create mode 100644 cdk_integration_tests/src/python/AppSyncFieldLevelLogs/pass.py create mode 100644 cdk_integration_tests/src/python/AppSyncLogging/fail__1__.py create mode 100644 cdk_integration_tests/src/python/AppSyncLogging/pass.py create mode 100644 cdk_integration_tests/src/python/AthenaWorkgroupConfiguration/fail__1__.py create mode 100644 cdk_integration_tests/src/python/AthenaWorkgroupConfiguration/pass.py create mode 100644 cdk_integration_tests/src/python/CloudTrailLogValidation/fail__1__.py create mode 100644 cdk_integration_tests/src/python/CloudTrailLogValidation/pass.py create mode 100644 cdk_integration_tests/src/python/DocDBAuditLogs/fail__1__.py create mode 100644 cdk_integration_tests/src/python/DocDBAuditLogs/pass.py create mode 100644 cdk_integration_tests/src/python/EFSEncryptionEnabled/fail__1__.py create mode 100644 cdk_integration_tests/src/python/EFSEncryptionEnabled/pass.py create mode 100644 cdk_integration_tests/src/python/ElasticacheReplicationGroupEncryptionAtRest/fail__1__.py create mode 100644 cdk_integration_tests/src/python/ElasticacheReplicationGroupEncryptionAtRest/pass.py create mode 100644 cdk_integration_tests/src/python/ElasticsearchDomainEnforceHTTPS/fail__1__.py create mode 100644 cdk_integration_tests/src/python/ElasticsearchDomainEnforceHTTPS/pass.py create mode 100644 cdk_integration_tests/src/python/IAMPolicyAttachedToGroupOrRoles/fail__1__.py create mode 100644 cdk_integration_tests/src/python/IAMPolicyAttachedToGroupOrRoles/pass.py create mode 100644 cdk_integration_tests/src/python/KinesisStreamEncryptionType/fail__1__.py create mode 100644 cdk_integration_tests/src/python/KinesisStreamEncryptionType/pass.py create mode 100644 cdk_integration_tests/src/python/RDSEnhancedMonitorEnabled/fail__1__.py create mode 100644 cdk_integration_tests/src/python/RDSEnhancedMonitorEnabled/pass.py create mode 100644 cdk_integration_tests/src/python/RDSPubliclyAccessible/fail__1__.py create mode 100644 cdk_integration_tests/src/python/RDSPubliclyAccessible/pass.py create mode 100644 cdk_integration_tests/src/python/RedshiftClusterPubliclyAccessible/fail__1__.py create mode 100644 cdk_integration_tests/src/python/RedshiftClusterPubliclyAccessible/pass.py create mode 100644 checkov/cdk/checks/python/APIGatewayAccessLogging.yaml create mode 100644 checkov/cdk/checks/python/AmazonMQBrokerPublicAccess.yaml create mode 100644 checkov/cdk/checks/python/AppSyncFieldLevelLogs.yaml create mode 100644 checkov/cdk/checks/python/AppSyncLogging.yaml create mode 100644 checkov/cdk/checks/python/AthenaWorkgroupConfiguration.yaml create mode 100644 checkov/cdk/checks/python/CloudTrailLogValidation.yaml create mode 100644 checkov/cdk/checks/python/DocDBAuditLogs.yaml create mode 100644 checkov/cdk/checks/python/EFSEncryptionEnabled.yaml create mode 100644 checkov/cdk/checks/python/ElasticacheReplicationGroupEncryptionAtRest.yaml create mode 100644 checkov/cdk/checks/python/ElasticsearchDomainEnforceHTTPS.yaml create mode 100644 checkov/cdk/checks/python/IAMPolicyAttachedToGroupOrRoles.yaml create mode 100644 checkov/cdk/checks/python/KinesisStreamEncryptionType.yaml create mode 100644 checkov/cdk/checks/python/RDSEnhancedMonitorEnabled.yaml create mode 100644 checkov/cdk/checks/python/RDSPubliclyAccessible.yaml create mode 100644 checkov/cdk/checks/python/RedshiftClusterPubliclyAccessible.yaml diff --git a/cdk_integration_tests/src/python/APIGatewayAccessLogging/fail__2__.py b/cdk_integration_tests/src/python/APIGatewayAccessLogging/fail__2__.py new file mode 100644 index 00000000000..021fd35b899 --- /dev/null +++ b/cdk_integration_tests/src/python/APIGatewayAccessLogging/fail__2__.py @@ -0,0 +1,66 @@ +from aws_cdk import aws_apigateway as apigateway + +cfn_stage = apigateway.CfnStage(self, "MyCfnStage", + rest_api_id="restApiId", + + # the properties below are optional + + cache_cluster_enabled=False, + cache_cluster_size="cacheClusterSize", + canary_setting=apigateway.CfnStage.CanarySettingProperty( + deployment_id="deploymentId", + percent_traffic=123, + stage_variable_overrides={ + "stage_variable_overrides_key": "stageVariableOverrides" + }, + use_stage_cache=False + ), + client_certificate_id="clientCertificateId", + deployment_id="deploymentId", + description="description", + documentation_version="documentationVersion", + method_settings=[apigateway.CfnStage.MethodSettingProperty( + cache_data_encrypted=False, + cache_ttl_in_seconds=123, + caching_enabled=False, + data_trace_enabled=False, + http_method="httpMethod", + logging_level="loggingLevel", + metrics_enabled=False, + resource_path="resourcePath", + throttling_burst_limit=123, + throttling_rate_limit=123 + )], + stage_name="stageName", + tags=[CfnTag( + key="key", + value="value" + )], + tracing_enabled=False, + variables={ + "variables_key": "variables" + } +) + +from aws_cdk import core +from aws_cdk import aws_serverless as serverless + +class ServerlessApiWithAccessLogStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create a Serverless API + serverless.Api( + self, "MyApi", + default_stage={ + "stage_name": "prod", + "access_log_setting": serverless.AccessLogSetting( + format=serverless.AccessLogFormat.json_with_standard_fields() + ) + } + ) + +app = core.App() +ServerlessApiWithAccessLogStack(app, "ServerlessApiWithAccessLogStack") +app.synth() diff --git a/cdk_integration_tests/src/python/APIGatewayAccessLogging/pass.py b/cdk_integration_tests/src/python/APIGatewayAccessLogging/pass.py new file mode 100644 index 00000000000..9ceb217cf46 --- /dev/null +++ b/cdk_integration_tests/src/python/APIGatewayAccessLogging/pass.py @@ -0,0 +1,70 @@ +from aws_cdk import aws_apigateway as apigateway + +cfn_stage = apigateway.CfnStage(self, "MyCfnStage", + rest_api_id="restApiId", + + # the properties below are optional + access_log_setting=apigateway.CfnStage.AccessLogSettingProperty( + destination_arn="destinationArn", + format="format" + ), + cache_cluster_enabled=False, + cache_cluster_size="cacheClusterSize", + canary_setting=apigateway.CfnStage.CanarySettingProperty( + deployment_id="deploymentId", + percent_traffic=123, + stage_variable_overrides={ + "stage_variable_overrides_key": "stageVariableOverrides" + }, + use_stage_cache=False + ), + client_certificate_id="clientCertificateId", + deployment_id="deploymentId", + description="description", + documentation_version="documentationVersion", + method_settings=[apigateway.CfnStage.MethodSettingProperty( + cache_data_encrypted=False, + cache_ttl_in_seconds=123, + caching_enabled=False, + data_trace_enabled=False, + http_method="httpMethod", + logging_level="loggingLevel", + metrics_enabled=False, + resource_path="resourcePath", + throttling_burst_limit=123, + throttling_rate_limit=123 + )], + stage_name="stageName", + tags=[CfnTag( + key="key", + value="value" + )], + tracing_enabled=False, + variables={ + "variables_key": "variables" + } +) + +from aws_cdk import core +from aws_cdk import aws_serverless as serverless + +class ServerlessApiWithAccessLogStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create a Serverless API + serverless.Api( + self, "MyApi", + default_stage={ + "stage_name": "prod", + "access_log_setting": serverless.AccessLogSetting( + destination_arn="arn:aws:logs:us-east-1:123456789012:log-group/MyLogGroup", + format=serverless.AccessLogFormat.json_with_standard_fields() + ) + } + ) + +app = core.App() +ServerlessApiWithAccessLogStack(app, "ServerlessApiWithAccessLogStack") +app.synth() diff --git a/cdk_integration_tests/src/python/AmazonMQBrokerPublicAccess/fail__1__.py b/cdk_integration_tests/src/python/AmazonMQBrokerPublicAccess/fail__1__.py new file mode 100644 index 00000000000..db491a845c4 --- /dev/null +++ b/cdk_integration_tests/src/python/AmazonMQBrokerPublicAccess/fail__1__.py @@ -0,0 +1,21 @@ +from aws_cdk import core +from aws_cdk import aws_amazonmq as amazonmq + +class AmazonMQStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create an Amazon MQ broker with PubliclyAccessible set to false + amazonmq_broker = amazonmq.CfnBroker( + self, + "MyAmazonMQBroker", + broker_name="my-amazon-mq-broker", + engine_type="ACTIVEMQ", + host_instance_type="mq.t2.micro", + publicly_accessible=True, # Set PubliclyAccessible to false + ) + +app = core.App() +AmazonMQStack(app, "AmazonMQStack") +app.synth() diff --git a/cdk_integration_tests/src/python/AmazonMQBrokerPublicAccess/pass.py b/cdk_integration_tests/src/python/AmazonMQBrokerPublicAccess/pass.py new file mode 100644 index 00000000000..a502f388ea3 --- /dev/null +++ b/cdk_integration_tests/src/python/AmazonMQBrokerPublicAccess/pass.py @@ -0,0 +1,21 @@ +from aws_cdk import core +from aws_cdk import aws_amazonmq as amazonmq + +class AmazonMQStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create an Amazon MQ broker with PubliclyAccessible set to false + amazonmq_broker = amazonmq.CfnBroker( + self, + "MyAmazonMQBroker", + broker_name="my-amazon-mq-broker", + engine_type="ACTIVEMQ", + host_instance_type="mq.t2.micro", + publicly_accessible=False, # Set PubliclyAccessible to false + ) + +app = core.App() +AmazonMQStack(app, "AmazonMQStack") +app.synth() diff --git a/cdk_integration_tests/src/python/AppSyncFieldLevelLogs/fail__1__.py b/cdk_integration_tests/src/python/AppSyncFieldLevelLogs/fail__1__.py new file mode 100644 index 00000000000..8f85e5784bc --- /dev/null +++ b/cdk_integration_tests/src/python/AppSyncFieldLevelLogs/fail__1__.py @@ -0,0 +1,24 @@ +from aws_cdk import core +from aws_cdk import aws_appsync as appsync + +class AppSyncStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Define the GraphQL API using CfnGraphQLApi + graphql_api = appsync.CfnGraphQLApi( + self, + "AppSyncGraphQLApi", + name="MyAppSyncAPI", + authentication_type="API_KEY", # You can change the authentication type + log_config=appsync.CfnGraphQLApi.LogConfigProperty( + cloud_watch_logs_role_arn="cloudWatchLogsRoleArn", + exclude_verbose_content=False, + ), + ) + + +app = core.App() +AppSyncStack(app, "AppSyncStack") +app.synth() diff --git a/cdk_integration_tests/src/python/AppSyncFieldLevelLogs/pass.py b/cdk_integration_tests/src/python/AppSyncFieldLevelLogs/pass.py new file mode 100644 index 00000000000..b1b501a3d25 --- /dev/null +++ b/cdk_integration_tests/src/python/AppSyncFieldLevelLogs/pass.py @@ -0,0 +1,25 @@ +from aws_cdk import core +from aws_cdk import aws_appsync as appsync + +class AppSyncStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Define the GraphQL API using CfnGraphQLApi + graphql_api = appsync.CfnGraphQLApi( + self, + "AppSyncGraphQLApi", + name="MyAppSyncAPI", + authentication_type="API_KEY", # You can change the authentication type + log_config=appsync.CfnGraphQLApi.LogConfigProperty( + cloud_watch_logs_role_arn="cloudWatchLogsRoleArn", + exclude_verbose_content=False, + field_log_level=appsync.FieldLogLevel.ALL + ), + ) + + +app = core.App() +AppSyncStack(app, "AppSyncStack") +app.synth() diff --git a/cdk_integration_tests/src/python/AppSyncLogging/fail__1__.py b/cdk_integration_tests/src/python/AppSyncLogging/fail__1__.py new file mode 100644 index 00000000000..feb147de4f7 --- /dev/null +++ b/cdk_integration_tests/src/python/AppSyncLogging/fail__1__.py @@ -0,0 +1,24 @@ +from aws_cdk import core +from aws_cdk import aws_appsync as appsync + +class AppSyncStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Define the GraphQL API using CfnGraphQLApi + graphql_api = appsync.CfnGraphQLApi( + self, + "AppSyncGraphQLApi", + name="MyAppSyncAPI", + authentication_type="API_KEY", # You can change the authentication type + log_config=appsync.CfnGraphQLApi.LogConfigProperty( + exclude_verbose_content=False, + field_log_level="fieldLogLevel" + ), + ) + + +app = core.App() +AppSyncStack(app, "AppSyncStack") +app.synth() diff --git a/cdk_integration_tests/src/python/AppSyncLogging/pass.py b/cdk_integration_tests/src/python/AppSyncLogging/pass.py new file mode 100644 index 00000000000..964cf20c7f5 --- /dev/null +++ b/cdk_integration_tests/src/python/AppSyncLogging/pass.py @@ -0,0 +1,25 @@ +from aws_cdk import core +from aws_cdk import aws_appsync as appsync + +class AppSyncStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Define the GraphQL API using CfnGraphQLApi + graphql_api = appsync.CfnGraphQLApi( + self, + "AppSyncGraphQLApi", + name="MyAppSyncAPI", + authentication_type="API_KEY", # You can change the authentication type + log_config=appsync.CfnGraphQLApi.LogConfigProperty( + cloud_watch_logs_role_arn="cloudWatchLogsRoleArn", + exclude_verbose_content=False, + field_log_level="fieldLogLevel" + ), + ) + + +app = core.App() +AppSyncStack(app, "AppSyncStack") +app.synth() diff --git a/cdk_integration_tests/src/python/AthenaWorkgroupConfiguration/fail__1__.py b/cdk_integration_tests/src/python/AthenaWorkgroupConfiguration/fail__1__.py new file mode 100644 index 00000000000..0e9b51f9799 --- /dev/null +++ b/cdk_integration_tests/src/python/AthenaWorkgroupConfiguration/fail__1__.py @@ -0,0 +1,28 @@ +from aws_cdk import core +from aws_cdk import aws_athena as athena + +class AthenaStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create an Athena WorkGroup + workgroup = athena.CfnWorkGroup( + self, + "MyAthenaWorkGroup", + name="my-workgroup", + description="My Athena WorkGroup", + state="ENABLED", # You can change the state + work_group_configuration=athena.CfnWorkGroup.WorkGroupConfigurationProperty( + additional_configuration="additionalConfiguration", + bytes_scanned_cutoff_per_query=123, + customer_content_encryption_configuration=athena.CfnWorkGroup.CustomerContentEncryptionConfigurationProperty( + kms_key="kmsKey" + ), + enforce_work_group_configuration=False, + ) + ) + +app = core.App() +AthenaStack(app, "AthenaStack") +app.synth() diff --git a/cdk_integration_tests/src/python/AthenaWorkgroupConfiguration/pass.py b/cdk_integration_tests/src/python/AthenaWorkgroupConfiguration/pass.py new file mode 100644 index 00000000000..0975419a19e --- /dev/null +++ b/cdk_integration_tests/src/python/AthenaWorkgroupConfiguration/pass.py @@ -0,0 +1,28 @@ +from aws_cdk import core +from aws_cdk import aws_athena as athena + +class AthenaStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create an Athena WorkGroup + workgroup = athena.CfnWorkGroup( + self, + "MyAthenaWorkGroup", + name="my-workgroup", + description="My Athena WorkGroup", + state="ENABLED", # You can change the state + work_group_configuration=athena.CfnWorkGroup.WorkGroupConfigurationProperty( + additional_configuration="additionalConfiguration", + bytes_scanned_cutoff_per_query=123, + customer_content_encryption_configuration=athena.CfnWorkGroup.CustomerContentEncryptionConfigurationProperty( + kms_key="kmsKey" + ), + enforce_work_group_configuration=True, + ) + ) + +app = core.App() +AthenaStack(app, "AthenaStack") +app.synth() diff --git a/cdk_integration_tests/src/python/CloudTrailLogValidation/fail__1__.py b/cdk_integration_tests/src/python/CloudTrailLogValidation/fail__1__.py new file mode 100644 index 00000000000..f8762347242 --- /dev/null +++ b/cdk_integration_tests/src/python/CloudTrailLogValidation/fail__1__.py @@ -0,0 +1,24 @@ +from aws_cdk import core +from aws_cdk import aws_cloudtrail as cloudtrail +from aws_cdk import aws_iam as iam + +class CloudTrailStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create an AWS CloudTrail trail using CfnTrail + trail = cloudtrail.CfnTrail( + self, + "MyCloudTrail", + is_logging=True, + enable_log_file_validation=False, + management_events=[ + cloudtrail.ReadWriteType.WRITE_ONLY, + ], + include_global_service_events=True, + ) + +app = core.App() +CloudTrailStack(app, "CloudTrailStack") +app.synth() diff --git a/cdk_integration_tests/src/python/CloudTrailLogValidation/pass.py b/cdk_integration_tests/src/python/CloudTrailLogValidation/pass.py new file mode 100644 index 00000000000..830da6d0302 --- /dev/null +++ b/cdk_integration_tests/src/python/CloudTrailLogValidation/pass.py @@ -0,0 +1,24 @@ +from aws_cdk import core +from aws_cdk import aws_cloudtrail as cloudtrail +from aws_cdk import aws_iam as iam + +class CloudTrailStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create an AWS CloudTrail trail using CfnTrail + trail = cloudtrail.CfnTrail( + self, + "MyCloudTrail", + is_logging=True, + enable_log_file_validation=True, # Enable log file validation + management_events=[ + cloudtrail.ReadWriteType.WRITE_ONLY, + ], + include_global_service_events=True, + ) + +app = core.App() +CloudTrailStack(app, "CloudTrailStack") +app.synth() diff --git a/cdk_integration_tests/src/python/DocDBAuditLogs/fail__1__.py b/cdk_integration_tests/src/python/DocDBAuditLogs/fail__1__.py new file mode 100644 index 00000000000..d6d178a67b9 --- /dev/null +++ b/cdk_integration_tests/src/python/DocDBAuditLogs/fail__1__.py @@ -0,0 +1,22 @@ +from aws_cdk import core +from aws_cdk import aws_docdb as docdb + +class DocDBStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Define the DocDB Cluster Parameter Group + db_parameter_group = docdb.CfnDBClusterParameterGroup( + self, + "DocDBClusterParameterGroup", + description="Custom DocDB Cluster Parameter Group", + family="docdb4.0", + parameters={ + "audit_logs": "disabled", + } + ) + +app = core.App() +DocDBStack(app, "DocDBStack") +app.synth() diff --git a/cdk_integration_tests/src/python/DocDBAuditLogs/pass.py b/cdk_integration_tests/src/python/DocDBAuditLogs/pass.py new file mode 100644 index 00000000000..716803e4398 --- /dev/null +++ b/cdk_integration_tests/src/python/DocDBAuditLogs/pass.py @@ -0,0 +1,22 @@ +from aws_cdk import core +from aws_cdk import aws_docdb as docdb + +class DocDBStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Define the DocDB Cluster Parameter Group + db_parameter_group = docdb.CfnDBClusterParameterGroup( + self, + "DocDBClusterParameterGroup", + description="Custom DocDB Cluster Parameter Group", + family="docdb4.0", + parameters={ + "audit_logs": "enabled", + } + ) + +app = core.App() +DocDBStack(app, "DocDBStack") +app.synth() diff --git a/cdk_integration_tests/src/python/EFSEncryptionEnabled/fail__1__.py b/cdk_integration_tests/src/python/EFSEncryptionEnabled/fail__1__.py new file mode 100644 index 00000000000..33b112ae788 --- /dev/null +++ b/cdk_integration_tests/src/python/EFSEncryptionEnabled/fail__1__.py @@ -0,0 +1,18 @@ +from aws_cdk import core +from aws_cdk import aws_efs as efs + +class EfsStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + efs_file_system = efs.FileSystem( + self, + "EfsFileSystem", + encrypted=False, # Set Encrypted property to False + lifecycle_policy=efs.LifecyclePolicy.AFTER_7_DAYS, + ) + +app = core.App() +EfsStack(app, "EfsStack") +app.synth() diff --git a/cdk_integration_tests/src/python/EFSEncryptionEnabled/pass.py b/cdk_integration_tests/src/python/EFSEncryptionEnabled/pass.py new file mode 100644 index 00000000000..a5ab1822d91 --- /dev/null +++ b/cdk_integration_tests/src/python/EFSEncryptionEnabled/pass.py @@ -0,0 +1,19 @@ +from aws_cdk import core +from aws_cdk import aws_efs as efs + +class EfsStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create an EFS file system with the Encrypted property set to True + efs_file_system = efs.FileSystem( + self, + "EfsFileSystem", + encrypted=True, # Set Encrypted property to True + lifecycle_policy=efs.LifecyclePolicy.AFTER_7_DAYS, + ) + +app = core.App() +EfsStack(app, "EfsStack") +app.synth() diff --git a/cdk_integration_tests/src/python/ElasticacheReplicationGroupEncryptionAtRest/fail__1__.py b/cdk_integration_tests/src/python/ElasticacheReplicationGroupEncryptionAtRest/fail__1__.py new file mode 100644 index 00000000000..f9d5d03bcea --- /dev/null +++ b/cdk_integration_tests/src/python/ElasticacheReplicationGroupEncryptionAtRest/fail__1__.py @@ -0,0 +1,26 @@ +from aws_cdk import core +from aws_cdk import aws_elasticache as elasticache + +class ElastiCacheReplicationGroupStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create an Amazon ElastiCache replication group + replication_group = elasticache.CfnReplicationGroup( + self, + "MyElastiCacheReplicationGroup", + replication_group_description="My Replication Group", + automatic_failover_enabled=True, + replication_group_id="my-replication-group", + cache_node_type="cache.m4.large", + engine="redis", + engine_version="5.0.6", + num_node_groups=2, + cache_subnet_group_name="my-subnet-group", + security_group_ids=["sg-0123456789abcdef0"], + ) + +app = core.App() +ElastiCacheReplicationGroupStack(app, "ElastiCacheReplicationGroupStack") +app.synth() diff --git a/cdk_integration_tests/src/python/ElasticacheReplicationGroupEncryptionAtRest/pass.py b/cdk_integration_tests/src/python/ElasticacheReplicationGroupEncryptionAtRest/pass.py new file mode 100644 index 00000000000..e5c0aa4e795 --- /dev/null +++ b/cdk_integration_tests/src/python/ElasticacheReplicationGroupEncryptionAtRest/pass.py @@ -0,0 +1,27 @@ +from aws_cdk import core +from aws_cdk import aws_elasticache as elasticache + +class ElastiCacheReplicationGroupStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create an Amazon ElastiCache replication group + replication_group = elasticache.CfnReplicationGroup( + self, + "MyElastiCacheReplicationGroup", + replication_group_description="My Replication Group", + automatic_failover_enabled=True, + replication_group_id="my-replication-group", + cache_node_type="cache.m4.large", + engine="redis", + engine_version="5.0.6", + num_node_groups=2, + cache_subnet_group_name="my-subnet-group", + security_group_ids=["sg-0123456789abcdef0"], + at_rest_encryption_enabled=True # Enable encryption at rest + ) + +app = core.App() +ElastiCacheReplicationGroupStack(app, "ElastiCacheReplicationGroupStack") +app.synth() diff --git a/cdk_integration_tests/src/python/ElasticsearchDomainEnforceHTTPS/fail__1__.py b/cdk_integration_tests/src/python/ElasticsearchDomainEnforceHTTPS/fail__1__.py new file mode 100644 index 00000000000..8d731aa6e26 --- /dev/null +++ b/cdk_integration_tests/src/python/ElasticsearchDomainEnforceHTTPS/fail__1__.py @@ -0,0 +1,26 @@ +from aws_cdk import core +from aws_cdk import aws_elasticsearch as elasticsearch + +class ElasticsearchStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create an Amazon Elasticsearch domain + elasticsearch_domain = elasticsearch.CfnDomain( + self, "MyElasticsearchDomain", + domain_name="my-elasticsearch-domain", + elasticsearch_version="7.10", + node_to_node_encryption_options={ + "enabled": True + }, + ebs_options={ + "ebsEnabled": True, + "volumeSize": 10 + }, + ) + +# Create the CDK app and stack +app = core.App() +ElasticsearchStack(app, "ElasticsearchStack") +app.synth() diff --git a/cdk_integration_tests/src/python/ElasticsearchDomainEnforceHTTPS/pass.py b/cdk_integration_tests/src/python/ElasticsearchDomainEnforceHTTPS/pass.py new file mode 100644 index 00000000000..c1fea468648 --- /dev/null +++ b/cdk_integration_tests/src/python/ElasticsearchDomainEnforceHTTPS/pass.py @@ -0,0 +1,33 @@ +from aws_cdk import core +from aws_cdk import aws_elasticsearch as elasticsearch + +class ElasticsearchStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create an Amazon Elasticsearch domain + elasticsearch_domain = elasticsearch.CfnDomain( + self, "MyElasticsearchDomain", + domain_name="my-elasticsearch-domain", + elasticsearch_version="7.10", + node_to_node_encryption_options={ + "enabled": True + }, + domain_endpoint_options=elasticsearch.CfnDomain.DomainEndpointOptionsProperty( + custom_endpoint="customEndpoint", + custom_endpoint_certificate_arn="customEndpointCertificateArn", + custom_endpoint_enabled=False, + enforce_https=True, + tls_security_policy="tlsSecurityPolicy" + ), + ebs_options={ + "ebsEnabled": True, + "volumeSize": 10 + }, + ) + +# Create the CDK app and stack +app = core.App() +ElasticsearchStack(app, "ElasticsearchStack") +app.synth() diff --git a/cdk_integration_tests/src/python/IAMPolicyAttachedToGroupOrRoles/fail__1__.py b/cdk_integration_tests/src/python/IAMPolicyAttachedToGroupOrRoles/fail__1__.py new file mode 100644 index 00000000000..bc8b5b6bd8e --- /dev/null +++ b/cdk_integration_tests/src/python/IAMPolicyAttachedToGroupOrRoles/fail__1__.py @@ -0,0 +1,27 @@ +from aws_cdk import core +from aws_cdk import aws_iam as iam + +class IAMStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create an IAM policy + custom_policy = iam.Policy( + self, + "CustomPolicy", + policy_name="MyCustomPolicy", + statements=[ + iam.PolicyStatement( + effect=iam.Effect.ALLOW, + actions=["s3:GetObject"], + resources=["arn:aws:s3:::my-bucket/*"], + ), + ], + users=["a"] + ) + + +app = core.App() +IAMStack(app, "IAMStack") +app.synth() diff --git a/cdk_integration_tests/src/python/IAMPolicyAttachedToGroupOrRoles/pass.py b/cdk_integration_tests/src/python/IAMPolicyAttachedToGroupOrRoles/pass.py new file mode 100644 index 00000000000..02618022235 --- /dev/null +++ b/cdk_integration_tests/src/python/IAMPolicyAttachedToGroupOrRoles/pass.py @@ -0,0 +1,26 @@ +from aws_cdk import core +from aws_cdk import aws_iam as iam + +class IAMStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create an IAM policy + custom_policy = iam.Policy( + self, + "CustomPolicy", + policy_name="MyCustomPolicy", + statements=[ + iam.PolicyStatement( + effect=iam.Effect.ALLOW, + actions=["s3:GetObject"], + resources=["arn:aws:s3:::my-bucket/*"], + ), + ], + ) + + +app = core.App() +IAMStack(app, "IAMStack") +app.synth() diff --git a/cdk_integration_tests/src/python/KinesisStreamEncryptionType/fail__1__.py b/cdk_integration_tests/src/python/KinesisStreamEncryptionType/fail__1__.py new file mode 100644 index 00000000000..3d7bf507e3d --- /dev/null +++ b/cdk_integration_tests/src/python/KinesisStreamEncryptionType/fail__1__.py @@ -0,0 +1,23 @@ +from aws_cdk import core +from aws_cdk import aws_kinesis as kinesis + +class KinesisStreamStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create an Amazon Kinesis stream + kinesis_stream = kinesis.CfnStream( + self, + "MyKinesisStream", + name="my-kinesis-stream", + shard_count=2, # The number of shards in the stream + stream_encryption={ + "encryption_type": "ABC", + "key_id": "YOUR_KMS_KEY_ID" # Replace with your KMS key ID + } + ) + +app = core.App() +KinesisStreamStack(app, "KinesisStreamStack") +app.synth() diff --git a/cdk_integration_tests/src/python/KinesisStreamEncryptionType/pass.py b/cdk_integration_tests/src/python/KinesisStreamEncryptionType/pass.py new file mode 100644 index 00000000000..91c9c57a21b --- /dev/null +++ b/cdk_integration_tests/src/python/KinesisStreamEncryptionType/pass.py @@ -0,0 +1,23 @@ +from aws_cdk import core +from aws_cdk import aws_kinesis as kinesis + +class KinesisStreamStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create an Amazon Kinesis stream + kinesis_stream = kinesis.CfnStream( + self, + "MyKinesisStream", + name="my-kinesis-stream", + shard_count=2, # The number of shards in the stream + stream_encryption={ + "encryption_type": "KMS", # Use KMS encryption + "key_id": "YOUR_KMS_KEY_ID" # Replace with your KMS key ID + } + ) + +app = core.App() +KinesisStreamStack(app, "KinesisStreamStack") +app.synth() diff --git a/cdk_integration_tests/src/python/RDSEnhancedMonitorEnabled/fail__1__.py b/cdk_integration_tests/src/python/RDSEnhancedMonitorEnabled/fail__1__.py new file mode 100644 index 00000000000..f9edfb246b0 --- /dev/null +++ b/cdk_integration_tests/src/python/RDSEnhancedMonitorEnabled/fail__1__.py @@ -0,0 +1,28 @@ +from aws_cdk import core +from aws_cdk import aws_rds as rds + +class RDSStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create an RDS DB instance with a custom MonitoringInterval + rds_instance = rds.DatabaseInstance( + self, + "MyRDSInstance", + engine=rds.DatabaseInstanceEngine.mysql( + version=rds.MysqlEngineVersion.VER_8_0 + ), + instance_type=core.Fn.select(0, core.Fn.split(" ", "db.m5.large")), + allocated_storage=20, + max_allocated_storage=100, + vpc_subnets={ + "subnetType": core.Fn.select(0, core.Fn.split(",", "private")), + }, + storage_type=rds.StorageType.GP2, + removal_policy=core.RemovalPolicy.DESTROY, + ) + +app = core.App() +RDSStack(app, "RDSStack") +app.synth() diff --git a/cdk_integration_tests/src/python/RDSEnhancedMonitorEnabled/pass.py b/cdk_integration_tests/src/python/RDSEnhancedMonitorEnabled/pass.py new file mode 100644 index 00000000000..ddd0f08f0d4 --- /dev/null +++ b/cdk_integration_tests/src/python/RDSEnhancedMonitorEnabled/pass.py @@ -0,0 +1,29 @@ +from aws_cdk import core +from aws_cdk import aws_rds as rds + +class RDSStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create an RDS DB instance with a custom MonitoringInterval + rds_instance = rds.DatabaseInstance( + self, + "MyRDSInstance", + engine=rds.DatabaseInstanceEngine.mysql( + version=rds.MysqlEngineVersion.VER_8_0 + ), + instance_type=core.Fn.select(0, core.Fn.split(" ", "db.m5.large")), + monitoring_interval=60, # Set MonitoringInterval to 60 seconds + allocated_storage=20, + max_allocated_storage=100, + vpc_subnets={ + "subnetType": core.Fn.select(0, core.Fn.split(",", "private")), + }, + storage_type=rds.StorageType.GP2, + removal_policy=core.RemovalPolicy.DESTROY, + ) + +app = core.App() +RDSStack(app, "RDSStack") +app.synth() diff --git a/cdk_integration_tests/src/python/RDSPubliclyAccessible/fail__1__.py b/cdk_integration_tests/src/python/RDSPubliclyAccessible/fail__1__.py new file mode 100644 index 00000000000..b5f68cc6e9e --- /dev/null +++ b/cdk_integration_tests/src/python/RDSPubliclyAccessible/fail__1__.py @@ -0,0 +1,29 @@ +from aws_cdk import core +from aws_cdk import aws_rds as rds + +class RDSStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create an RDS DB instance with PubliclyAccessible set to True + rds_instance = rds.DatabaseInstance( + self, + "MyRDSInstance", + engine=rds.DatabaseInstanceEngine.mysql( + version=rds.MysqlEngineVersion.VER_8_0 + ), + instance_type=core.Fn.select(0, core.Fn.split(" ", "db.m5.large")), + publicly_accessible=True, # Set PubliclyAccessible to True + allocated_storage=20, + max_allocated_storage=100, + vpc_subnets={ + "subnetType": core.Fn.select(0, core.Fn.split(",", "private")), + }, + storage_type=rds.StorageType.GP2, + removal_policy=core.RemovalPolicy.DESTROY, + ) + +app = core.App() +RDSStack(app, "RDSStack") +app.synth() diff --git a/cdk_integration_tests/src/python/RDSPubliclyAccessible/pass.py b/cdk_integration_tests/src/python/RDSPubliclyAccessible/pass.py new file mode 100644 index 00000000000..f364e531d42 --- /dev/null +++ b/cdk_integration_tests/src/python/RDSPubliclyAccessible/pass.py @@ -0,0 +1,29 @@ +from aws_cdk import core +from aws_cdk import aws_rds as rds + +class RDSStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create an RDS DB instance with PubliclyAccessible set to false + rds_instance = rds.DatabaseInstance( + self, + "MyRDSInstance", + engine=rds.DatabaseInstanceEngine.mysql( + version=rds.MysqlEngineVersion.VER_8_0 + ), + instance_type=core.Fn.select(0, core.Fn.split(" ", "db.m5.large")), + publicly_accessible=False, # Set PubliclyAccessible to false + allocated_storage=20, + max_allocated_storage=100, + vpc_subnets={ + "subnetType": core.Fn.select(0, core.Fn.split(",", "private")), + }, + storage_type=rds.StorageType.GP2, + removal_policy=core.RemovalPolicy.DESTROY, + ) + +app = core.App() +RDSStack(app, "RDSStack") +app.synth() diff --git a/cdk_integration_tests/src/python/RedshiftClusterPubliclyAccessible/fail__1__.py b/cdk_integration_tests/src/python/RedshiftClusterPubliclyAccessible/fail__1__.py new file mode 100644 index 00000000000..1df7f77775a --- /dev/null +++ b/cdk_integration_tests/src/python/RedshiftClusterPubliclyAccessible/fail__1__.py @@ -0,0 +1,22 @@ +from aws_cdk import core +from aws_cdk import aws_redshift as redshift + +class RedshiftStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create a Redshift cluster with PubliclyAccessible set to true + redshift_cluster = redshift.CfnCluster( + self, + "MyRedshiftCluster", + cluster_identifier="my-redshift-cluster", + node_type="dc2.large", + publicly_accessible=True, # Set PubliclyAccessible to true + master_username="admin", + master_user_password="MyPassword123", # checkov:skip=CKV_SECRET_6 test secret + ) + +app = core.App() +RedshiftStack(app, "RedshiftStack") +app.synth() diff --git a/cdk_integration_tests/src/python/RedshiftClusterPubliclyAccessible/pass.py b/cdk_integration_tests/src/python/RedshiftClusterPubliclyAccessible/pass.py new file mode 100644 index 00000000000..9e0718d35dd --- /dev/null +++ b/cdk_integration_tests/src/python/RedshiftClusterPubliclyAccessible/pass.py @@ -0,0 +1,22 @@ +from aws_cdk import core +from aws_cdk import aws_redshift as redshift + +class RedshiftStack(core.Stack): + + def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + # Create a Redshift cluster with PubliclyAccessible set to False + redshift_cluster = redshift.CfnCluster( + self, + "MyRedshiftCluster", + cluster_identifier="my-redshift-cluster", + node_type="dc2.large", + publicly_accessible=False, # Set PubliclyAccessible to False + master_username="admin", + master_user_password="MyPassword123", # checkov:skip=CKV_SECRET_6 test secret + ) + +app = core.App() +RedshiftStack(app, "RedshiftStack") +app.synth() diff --git a/cdk_integration_tests/src/python/WAFEnabled/fail__1__.py b/cdk_integration_tests/src/python/WAFEnabled/fail__1__.py index 035ec68ebf2..f7b644ab7a5 100644 --- a/cdk_integration_tests/src/python/WAFEnabled/fail__1__.py +++ b/cdk_integration_tests/src/python/WAFEnabled/fail__1__.py @@ -2,7 +2,6 @@ from aws_cdk import aws_cloudfront as cloudfront class CloudFrontDistributionStack(core.Stack): - def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) @@ -20,4 +19,4 @@ def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: app = core.App() CloudFrontDistributionStack(app, "CloudFrontDistributionStack") -app.synth() +app.synth() \ No newline at end of file diff --git a/cdk_integration_tests/test_checks_python.py b/cdk_integration_tests/test_checks_python.py index 3e699ed3c3b..8ee1a33b09c 100644 --- a/cdk_integration_tests/test_checks_python.py +++ b/cdk_integration_tests/test_checks_python.py @@ -14,128 +14,192 @@ def failed_checks() -> Dict[str, List[Dict[str, Any]]]: def test_CKV_AWS_18_S3BucketLogging(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_18") + run_check(check_results=failed_checks, check_id="CKV_AWS_18", policy_name="S3BucketLogging", language="python") def test_CKV_AWS_19_S3BucketEncryption(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_19") + run_check(check_results=failed_checks, check_id="CKV_AWS_19", policy_name="S3BucketEncryption", language="python") def test_CKV_AWS_21_S3BucketVersioning(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_21") + run_check(check_results=failed_checks, check_id="CKV_AWS_21", policy_name="S3BucketVersioning", language="python") def test_CKV_AWS_145_S3BucketKMSEncryption(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_145") + run_check(check_results=failed_checks, check_id="CKV_AWS_145", policy_name="S3BucketKMSEncryption", language="python") def test_CKV2_AWS_6_S3BucketPublicAccessBlock(failed_checks): - run_check(check_results=failed_checks, check_id="CKV2_AWS_6") + run_check(check_results=failed_checks, check_id="CKV2_AWS_6", policy_name="S3BucketPublicAccessBlock", language="python") def test_CKV_AWS_54_S3BlockPublicPolicy(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_54") + run_check(check_results=failed_checks, check_id="CKV_AWS_54", policy_name="S3BlockPublicPolicy", language="python") def test_CKV_AWS_26_SNSTopicEncryption(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_26") + run_check(check_results=failed_checks, check_id="CKV_AWS_26", policy_name="SNSTopicEncryption", language="python") def test_CKV_AWS_20_S3PublicACLRead(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_20") + run_check(check_results=failed_checks, check_id="CKV_AWS_20", policy_name="S3PublicACLRead", language="python") def test_CKV_AWS_55_S3IgnorePublicACLs(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_55") + run_check(check_results=failed_checks, check_id="CKV_AWS_55", policy_name="S3IgnorePublicACLs", language="python") def test_CKV_AWS_56_S3RestrictPublicBuckets(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_56") + run_check(check_results=failed_checks, check_id="CKV_AWS_56", policy_name="S3RestrictPublicBuckets", language="python") def test_CKV_AWS_53_S3BlockPublicACLs(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_53") + run_check(check_results=failed_checks, check_id="CKV_AWS_53", policy_name="S3BlockPublicACLs", language="python") def test_CKV_AWS_57_S3PublicACLWrite(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_57") + run_check(check_results=failed_checks, check_id="CKV_AWS_57", policy_name="S3PublicACLWrite", language="python") def test_CKV_AWS_115_LambdaFunctionLevelConcurrentExecutionLimit(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_115") + run_check(check_results=failed_checks, check_id="CKV_AWS_115", policy_name="LambdaFunctionLevelConcurrentExecutionLimit", language="python") def test_CKV_AWS_116_LambdaDLQConfigured(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_116") + run_check(check_results=failed_checks, check_id="CKV_AWS_116", policy_name="LambdaDLQConfigured", language="python") def test_CKV_AWS_28_DynamodbRecovery(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_28") + run_check(check_results=failed_checks, check_id="CKV_AWS_28", policy_name="DynamodbRecovery", language="python") def test_CKV_AWS_158_CloudWatchLogGroupKMSKey(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_158") + run_check(check_results=failed_checks, check_id="CKV_AWS_158", policy_name="CloudWatchLogGroupKMSKey", language="python") def test_CKV_AWS_3_EBSEncryption(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_3") + run_check(check_results=failed_checks, check_id="CKV_AWS_3", policy_name="EBSEncryption", language="python") def test_CKV_AWS_120_APIGatewayCacheEnable(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_120") + run_check(check_results=failed_checks, check_id="CKV_AWS_120", policy_name="APIGatewayCacheEnable", language="python") def test_CKV_AWS_163_ECRImageScanning(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_163") + run_check(check_results=failed_checks, check_id="CKV_AWS_163", policy_name="ECRImageScanning", language="python") def test_CKV_AWS_51_ECRImmutableTags(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_51") + run_check(check_results=failed_checks, check_id="CKV_AWS_51", policy_name="ECRImmutableTags", language="python") def test_CKV_AWS_44_NeptuneClusterStorageEncrypted(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_44") + run_check(check_results=failed_checks, check_id="CKV_AWS_44", policy_name="NeptuneClusterStorageEncrypted", language="python") def test_CKV_AWS_166_BackupVaultEncrypted(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_166") + run_check(check_results=failed_checks, check_id="CKV_AWS_166", policy_name="BackupVaultEncrypted", language="python") def test_CKV_AWS_74_DocDBEncryption(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_74") + run_check(check_results=failed_checks, check_id="CKV_AWS_74", policy_name="DocDBEncryption", language="python") def test_CKV_AWS_47_DAXEncryption(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_47") + run_check(check_results=failed_checks, check_id="CKV_AWS_47", policy_name="DAXEncryption", language="python") def test_CKV_AWS_156_WorkspaceRootVolumeEncrypted(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_156") + run_check(check_results=failed_checks, check_id="CKV_AWS_156", policy_name="WorkspaceRootVolumeEncrypted", language="python") def test_CKV_AWS_155_WorkspaceUserVolumeEncrypted(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_155") + run_check(check_results=failed_checks, check_id="CKV_AWS_155", policy_name="WorkspaceUserVolumeEncrypted", language="python") def test_CKV_AWS_165_DynamodbGlobalTableRecovery(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_165") + run_check(check_results=failed_checks, check_id="CKV_AWS_165", policy_name="DynamodbGlobalTableRecovery", language="python") def test_CKV_AWS_27_SQSQueueEncryption(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_27") + run_check(check_results=failed_checks, check_id="CKV_AWS_27", policy_name="SQSQueueEncryption", language="python") def test_CKV_AWS_195_GlueSecurityConfigurationEnabled(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_195") + run_check(check_results=failed_checks, check_id="CKV_AWS_195", policy_name="GlueSecurityConfigurationEnabled", language="python") def test_CKV_AWS_30_ElasticacheReplicationGroupEncryptionAtTransit(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_30") + run_check(check_results=failed_checks, check_id="CKV_AWS_30", policy_name="ElasticacheReplicationGroupEncryptionAtTransit", language="python") + + +def test_CKV_AWS_29_ElasticacheReplicationGroupEncryptionAtRest(failed_checks): + run_check(check_results=failed_checks, check_id="CKV_AWS_29", policy_name="ElasticacheReplicationGroupEncryptionAtRest", language="python") + + +def test_CKV_AWS_43_KinesisStreamEncryptionType(failed_checks): + run_check(check_results=failed_checks, check_id="CKV_AWS_43", policy_name="KinesisStreamEncryptionType", language="python") + + +def test_CKV_AWS_42_EFSEncryptionEnabled(failed_checks): + run_check(check_results=failed_checks, check_id="CKV_AWS_42", policy_name="EFSEncryptionEnabled", language="python") + + +def test_CKV_AWS_193_AppSyncLogging(failed_checks): + run_check(check_results=failed_checks, check_id="CKV_AWS_193", policy_name="AppSyncLogging", language="python") + + +def test_CKV_AWS_194_AppSyncFieldLevelLogs(failed_checks): + run_check(check_results=failed_checks, check_id="CKV_AWS_194", policy_name="AppSyncFieldLevelLogs", language="python") + + +def test_CKV_AWS_104_DocDBAuditLogs(failed_checks): + run_check(check_results=failed_checks, check_id="CKV_AWS_104", policy_name="DocDBAuditLogs", language="python") + + +def test_CKV_AWS_82_AthenaWorkgroupConfiguration(failed_checks): + run_check(check_results=failed_checks, check_id="CKV_AWS_82", policy_name="AthenaWorkgroupConfiguration", language="python") + + +def test_CKV_AWS_17_RDSPubliclyAccessible(failed_checks): + run_check(check_results=failed_checks, check_id="CKV_AWS_17", policy_name="RDSPubliclyAccessible", language="python") + + +def test_CKV_AWS_87_RedshiftClusterPubliclyAccessible(failed_checks): + run_check(check_results=failed_checks, check_id="CKV_AWS_87", policy_name="RedshiftClusterPubliclyAccessible", language="python") + + +def test_CKV_AWS_69_AmazonMQBrokerPublicAccess(failed_checks): + run_check(check_results=failed_checks, check_id="CKV_AWS_69", policy_name="AmazonMQBrokerPublicAccess", language="python") + + +def test_CKV_AWS_118_RDSEnhancedMonitorEnabled(failed_checks): + run_check(check_results=failed_checks, check_id="CKV_AWS_118", policy_name="RDSEnhancedMonitorEnabled", language="python") + + +def test_CKV_AWS_40_IAMPolicyAttachedToGroupOrRoles(failed_checks): + run_check(check_results=failed_checks, check_id="CKV_AWS_40", policy_name="IAMPolicyAttachedToGroupOrRoles", language="python") + + +def test_CKV_AWS_36_CloudTrailLogValidation(failed_checks): + run_check(check_results=failed_checks, check_id="CKV_AWS_36", policy_name="CloudTrailLogValidation", language="python") + + +def test_CKV_AWS_83_ElasticsearchDomainEnforceHTTPS(failed_checks): + run_check(check_results=failed_checks, check_id="CKV_AWS_83", policy_name="ElasticsearchDomainEnforceHTTPS", language="python") + + +def test_CKV_AWS_76_APIGatewayAccessLogging(failed_checks): + run_check(check_results=failed_checks, check_id="CKV_AWS_76", policy_name="APIGatewayAccessLogging", language="python") + + +def test_CKV_AWS_117_LambdaInVPC(failed_checks): + run_check(check_results=failed_checks, check_id="CKV_AWS_117", policy_name="LambdaInVPC", language="python") def test_CKV_AWS_68_WAFEnabled(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_68") + run_check(check_results=failed_checks, check_id="CKV_AWS_68", policy_name="WAFEnabled", language="python") def test_CKV_AWS_64_RedshiftClusterEncryption(failed_checks): - run_check(check_results=failed_checks, check_id="CKV_AWS_64") + run_check(check_results=failed_checks, check_id="CKV_AWS_64", policy_name="RedshiftClusterEncryption", language="python") diff --git a/cdk_integration_tests/utils.py b/cdk_integration_tests/utils.py index 09ddd6d305e..a8e68f87dcb 100644 --- a/cdk_integration_tests/utils.py +++ b/cdk_integration_tests/utils.py @@ -1,6 +1,7 @@ import json import os from typing import List, Dict, Any +import yaml current_dir = os.path.dirname(os.path.realpath(__file__)) @@ -22,7 +23,17 @@ def load_failed_checks_from_file(lang: str) -> Dict[str, List[Dict[str, Any]]]: return results -def run_check(check_results: Dict[str, List[Dict[str, Any]]], check_id: str) -> None: +def is_policy_with_correct_check_id(check_id: str, language: str, policy_name: str) -> bool: + path = os.path.join(current_dir, '..', 'checkov', 'cdk', 'checks', language, policy_name + ".yaml") + with open(path, 'r') as file: + data = yaml.safe_load(file) + if 'metadata' in data and 'id' in data['metadata'] and data['metadata']['id'] == check_id: + return True + return False + + +def run_check(check_results: Dict[str, List[Dict[str, Any]]], check_id: str, policy_name: str, language: str) -> None: + assert is_policy_with_correct_check_id(check_id, language, policy_name) results_for_check_id = check_results.get(check_id) assert results_for_check_id diff --git a/checkov/cdk/checks/python/APIGatewayAccessLogging.yaml b/checkov/cdk/checks/python/APIGatewayAccessLogging.yaml new file mode 100644 index 00000000000..8c7f07cc461 --- /dev/null +++ b/checkov/cdk/checks/python/APIGatewayAccessLogging.yaml @@ -0,0 +1,27 @@ +metadata: + version: 0.2 + approach: define failing + id: CKV_AWS_76 + name: Ensure API Gateway has Access Logging enabled + category: LOGGING +scope: + languages: + - python +definition: + patterns: + or: + - pattern: aws_cdk.aws_apigateway.CfnStage() + conditions: + - not_pattern: aws_cdk.aws_apigateway.CfnStage(, access_log_setting=aws_cdk.aws_apigateway.CfnStage.AccessLogSettingProperty(, destination_arn=$ARG , ) , ) + - not_pattern: | + $P = aws_cdk.aws_apigateway.CfnStage.AccessLogSettingProperty(, destination_arn=$ARG , ) + + aws_cdk.aws_apigateway.CfnStage(, access_log_setting=$P, ) + - pattern: aws_cdk.aws_serverless.Api() + conditions: + - not_pattern: | + aws_cdk.aws_serverless.Api(, default_stage={, "access_log_setting": aws_cdk.aws_serverless.AccessLogSetting(, destination_arn=$ARG,), } , ) + - not_pattern: | + $P = aws_cdk.aws_serverless.AccessLogSetting(, destination_arn=$ARG , ) + + aws_cdk.aws_serverless.Api(, default_stage={, "access_log_setting": $P, }, ) diff --git a/checkov/cdk/checks/python/AmazonMQBrokerPublicAccess.yaml b/checkov/cdk/checks/python/AmazonMQBrokerPublicAccess.yaml new file mode 100644 index 00000000000..700fc350a7f --- /dev/null +++ b/checkov/cdk/checks/python/AmazonMQBrokerPublicAccess.yaml @@ -0,0 +1,11 @@ +metadata: + version: 0.2 + approach: define failing + id: CKV_AWS_69 + name: Ensure Amazon MQ Broker should not have public access + category: GENERAL_SECURITY +scope: + languages: + - python +definition: + pattern: aws_cdk.aws_amazonmq.CfnBroker(, publicly_accessible=True , ) \ No newline at end of file diff --git a/checkov/cdk/checks/python/AppSyncFieldLevelLogs.yaml b/checkov/cdk/checks/python/AppSyncFieldLevelLogs.yaml new file mode 100644 index 00000000000..eca453b68d9 --- /dev/null +++ b/checkov/cdk/checks/python/AppSyncFieldLevelLogs.yaml @@ -0,0 +1,22 @@ +metadata: + version: 0.2 + approach: define failing + id: CKV_AWS_194 + name: Ensure AppSync has Field-Level logs enabled + category: LOGGING +scope: + languages: + - python +definition: + pattern: aws_cdk.aws_appsync.CfnGraphQLApi() + conditions: + - not_pattern: + source: aws_cdk.aws_appsync.CfnGraphQLApi.LogConfigProperty(, field_log_level=aws_cdk.aws_appsync.FieldLogLevel.$ARG , ) + sink: aws_cdk.aws_appsync.CfnGraphQLApi(, log_config=$LOG , ) + - not_pattern: aws_cdk.aws_appsync.CfnGraphQLApi(, log_config=aws_cdk.aws_appsync.CfnGraphQLApi.LogConfigProperty(, field_log_level=aws_cdk.aws_appsync.FieldLogLevel.$ARG , ) , ) + - not_pattern: | + $LOG = aws_cdk.aws_appsync.CfnGraphQLApi.LogConfigProperty(, field_log_level=aws_cdk.aws_appsync.FieldLogLevel.$ARG , ) + + aws_cdk.aws_appsync.CfnGraphQLApi(, log_config=$LOG , ) + - metavariable: $ARG + regex: (ERRORS|ALL) \ No newline at end of file diff --git a/checkov/cdk/checks/python/AppSyncLogging.yaml b/checkov/cdk/checks/python/AppSyncLogging.yaml new file mode 100644 index 00000000000..85a5db59f38 --- /dev/null +++ b/checkov/cdk/checks/python/AppSyncLogging.yaml @@ -0,0 +1,17 @@ +metadata: + version: 0.2 + approach: define failing + id: CKV_AWS_193 + name: Ensure AppSync has Logging enabled + category: LOGGING +scope: + languages: + - python +definition: + pattern: aws_cdk.aws_appsync.CfnGraphQLApi() + conditions: + - not_pattern: aws_cdk.aws_appsync.CfnGraphQLApi(, log_config=aws_cdk.aws_appsync.CfnGraphQLApi.LogConfigProperty(, cloud_watch_logs_role_arn=$ARG , ) , ) + - not_pattern: | + $LOG = aws_cdk.aws_appsync.CfnGraphQLApi.LogConfigProperty(, cloud_watch_logs_role_arn=$ARG , ) + + aws_cdk.aws_appsync.CfnGraphQLApi(, log_config=$LOG , ) \ No newline at end of file diff --git a/checkov/cdk/checks/python/AthenaWorkgroupConfiguration.yaml b/checkov/cdk/checks/python/AthenaWorkgroupConfiguration.yaml new file mode 100644 index 00000000000..ef497c8d813 --- /dev/null +++ b/checkov/cdk/checks/python/AthenaWorkgroupConfiguration.yaml @@ -0,0 +1,17 @@ +metadata: + version: 0.2 + approach: define failing + id: CKV_AWS_82 + name: Ensure Athena Workgroup should enforce configuration to prevent client disabling encryption + category: GENERAL_SECURITY +scope: + languages: + - python +definition: + pattern: aws_cdk.aws_athena.CfnWorkGroup() + conditions: + - not_pattern: aws_cdk.aws_athena.CfnWorkGroup(, work_group_configuration=aws_cdk.aws_athena.CfnWorkGroup.WorkGroupConfigurationProperty(, enforce_work_group_configuration=True , ) , ) + - not_pattern: | + $ARG = aws_cdk.aws_athena.CfnWorkGroup.WorkGroupConfigurationProperty(, enforce_work_group_configuration=True , ) + + aws_cdk.aws_athena.CfnWorkGroup(, work_group_configuration=$ARG , ) \ No newline at end of file diff --git a/checkov/cdk/checks/python/CloudTrailLogValidation.yaml b/checkov/cdk/checks/python/CloudTrailLogValidation.yaml new file mode 100644 index 00000000000..239e1191a41 --- /dev/null +++ b/checkov/cdk/checks/python/CloudTrailLogValidation.yaml @@ -0,0 +1,13 @@ +metadata: + version: 0.2 + approach: define failing + id: CKV_AWS_36 + name: Ensure CloudTrail log file validation is enabled + category: LOGGING +scope: + languages: + - python +definition: + pattern: aws_cdk.aws_cloudtrail.CfnTrail() + conditions: + - not_pattern: aws_cdk.aws_cloudtrail.CfnTrail(, enable_log_file_validation=True , ) \ No newline at end of file diff --git a/checkov/cdk/checks/python/DocDBAuditLogs.yaml b/checkov/cdk/checks/python/DocDBAuditLogs.yaml new file mode 100644 index 00000000000..569e435fc73 --- /dev/null +++ b/checkov/cdk/checks/python/DocDBAuditLogs.yaml @@ -0,0 +1,13 @@ +metadata: + version: 0.2 + approach: define failing + id: CKV_AWS_104 + name: Ensure DocDB has audit logs enabled + category: LOGGING +scope: + languages: + - python +definition: + pattern: aws_cdk.aws_docdb.CfnDBClusterParameterGroup() + conditions: + - not_pattern: 'aws_cdk.aws_docdb.CfnDBClusterParameterGroup(, parameters={, "audit_logs": "enabled" , } , )' \ No newline at end of file diff --git a/checkov/cdk/checks/python/EFSEncryptionEnabled.yaml b/checkov/cdk/checks/python/EFSEncryptionEnabled.yaml new file mode 100644 index 00000000000..b3195be4467 --- /dev/null +++ b/checkov/cdk/checks/python/EFSEncryptionEnabled.yaml @@ -0,0 +1,13 @@ +metadata: + version: 0.2 + approach: define failing + id: CKV_AWS_42 + name: Ensure EFS is securely encrypted + category: ENCRYPTION +scope: + languages: + - python +definition: + pattern: aws_cdk.aws_efs.FileSystem() + conditions: + - not_pattern: aws_cdk.aws_efs.FileSystem(, encrypted=True, ) \ No newline at end of file diff --git a/checkov/cdk/checks/python/ElasticacheReplicationGroupEncryptionAtRest.yaml b/checkov/cdk/checks/python/ElasticacheReplicationGroupEncryptionAtRest.yaml new file mode 100644 index 00000000000..10f4d7cc694 --- /dev/null +++ b/checkov/cdk/checks/python/ElasticacheReplicationGroupEncryptionAtRest.yaml @@ -0,0 +1,13 @@ +metadata: + version: 0.2 + approach: define failing + id: CKV_AWS_29 + name: Ensure all data stored in the Elasticache Replication Group is securely encrypted at rest + category: ENCRYPTION +scope: + languages: + - python +definition: + pattern: aws_cdk.aws_elasticache.CfnReplicationGroup() + conditions: + - not_pattern: aws_cdk.aws_elasticache.CfnReplicationGroup(, at_rest_encryption_enabled=True, ) \ No newline at end of file diff --git a/checkov/cdk/checks/python/ElasticsearchDomainEnforceHTTPS.yaml b/checkov/cdk/checks/python/ElasticsearchDomainEnforceHTTPS.yaml new file mode 100644 index 00000000000..050d537c000 --- /dev/null +++ b/checkov/cdk/checks/python/ElasticsearchDomainEnforceHTTPS.yaml @@ -0,0 +1,17 @@ +metadata: + version: 0.2 + approach: define failing + id: CKV_AWS_83 + name: Ensure Elasticsearch Domain enforces HTTPS + category: ENCRYPTION +scope: + languages: + - python +definition: + pattern: aws_cdk.aws_elasticsearch.CfnDomain() + conditions: + - not_pattern: aws_cdk.aws_elasticsearch.CfnDomain(, domain_endpoint_options=aws_cdk.aws_elasticsearch.CfnDomain.DomainEndpointOptionsProperty(, enforce_https=True , ) , ) + - not_pattern: | + $P = aws_cdk.aws_elasticsearch.CfnDomain.DomainEndpointOptionsProperty(, enforce_https=True , ) + + aws_cdk.aws_elasticsearch.CfnDomain(, domain_endpoint_options=$P , ) \ No newline at end of file diff --git a/checkov/cdk/checks/python/IAMPolicyAttachedToGroupOrRoles.yaml b/checkov/cdk/checks/python/IAMPolicyAttachedToGroupOrRoles.yaml new file mode 100644 index 00000000000..856e9fe1b3e --- /dev/null +++ b/checkov/cdk/checks/python/IAMPolicyAttachedToGroupOrRoles.yaml @@ -0,0 +1,17 @@ +metadata: + version: 0.2 + approach: define failing + id: CKV_AWS_40 + name: Ensure IAM policies are attached only to groups or roles (Reducing access management complexity may in-turn reduce opportunity for a principal to inadvertently receive or retain excessive privileges.) + category: IAM +scope: + languages: + - python +definition: + patterns: + or: + - pattern: aws_cdk.aws_iam.Policy(, users=[], ) + - pattern: | + $P = aws_cdk.aws_iam.Policy() + + $P.attachToUser() \ No newline at end of file diff --git a/checkov/cdk/checks/python/KinesisStreamEncryptionType.yaml b/checkov/cdk/checks/python/KinesisStreamEncryptionType.yaml new file mode 100644 index 00000000000..b20d1fa61ba --- /dev/null +++ b/checkov/cdk/checks/python/KinesisStreamEncryptionType.yaml @@ -0,0 +1,14 @@ +metadata: + version: 0.2 + approach: define failing + id: CKV_AWS_43 + name: Ensure Kinesis Stream is securely encrypted + category: ENCRYPTION +scope: + languages: + - python +definition: + pattern: aws_cdk.aws_kinesis.CfnStream() + conditions: + - not_pattern: | + aws_cdk.aws_kinesis.CfnStream(, stream_encryption={, "encryption_type": "KMS", } , ) \ No newline at end of file diff --git a/checkov/cdk/checks/python/RDSEnhancedMonitorEnabled.yaml b/checkov/cdk/checks/python/RDSEnhancedMonitorEnabled.yaml new file mode 100644 index 00000000000..1eb5cc13de2 --- /dev/null +++ b/checkov/cdk/checks/python/RDSEnhancedMonitorEnabled.yaml @@ -0,0 +1,15 @@ +metadata: + version: 0.2 + approach: define failing + id: CKV_AWS_118 + name: Ensure that enhanced monitoring is enabled for Amazon RDS instances + category: LOGGING +scope: + languages: + - python +definition: + pattern: aws_cdk.aws_rds.DatabaseInstance() + conditions: + - not_pattern: aws_cdk.aws_rds.DatabaseInstance(, monitoring_interval=$COUNT , ) + - metavariable: $COUNT + comparison: $COUNT != 0 diff --git a/checkov/cdk/checks/python/RDSPubliclyAccessible.yaml b/checkov/cdk/checks/python/RDSPubliclyAccessible.yaml new file mode 100644 index 00000000000..26e54fbcc5e --- /dev/null +++ b/checkov/cdk/checks/python/RDSPubliclyAccessible.yaml @@ -0,0 +1,11 @@ +metadata: + version: 0.2 + approach: define failing + id: CKV_AWS_17 + name: Ensure all data stored in RDS is not publicly accessible + category: NETWORKING +scope: + languages: + - python +definition: + pattern: aws_cdk.aws_rds.DatabaseInstance(, publicly_accessible=True , ) diff --git a/checkov/cdk/checks/python/RedshiftClusterPubliclyAccessible.yaml b/checkov/cdk/checks/python/RedshiftClusterPubliclyAccessible.yaml new file mode 100644 index 00000000000..5c7f1201a3b --- /dev/null +++ b/checkov/cdk/checks/python/RedshiftClusterPubliclyAccessible.yaml @@ -0,0 +1,11 @@ +metadata: + version: 0.2 + approach: define failing + id: CKV_AWS_87 + name: Redshift cluster should not be publicly accessible + category: NETWORKING +scope: + languages: + - python +definition: + pattern: aws_cdk.aws_redshift.CfnCluster(, publicly_accessible=True , )