diff --git a/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/metadata.json b/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/metadata.json index 2d7173cf948..263904686f3 100644 --- a/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/metadata.json +++ b/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/metadata.json @@ -4,7 +4,7 @@ "severity": "HIGH", "category": "Encryption", "descriptionText": "Cloud SQL Database Instance should have SSL enabled", - "descriptionUrl": "https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_database_instance#require_ssl", + "descriptionUrl": "https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_database_instance#ssl_mode-1", "platform": "Terraform", "descriptionID": "8983549e", "cloudProvider": "gcp", diff --git a/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/query.rego b/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/query.rego index ca8961c9785..af1fd89f26f 100644 --- a/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/query.rego +++ b/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/query.rego @@ -3,6 +3,8 @@ package Cx import data.generic.common as common_lib import data.generic.terraform as tf_lib +allowed_ssl_modes := ["ENCRYPTED_ONLY", "TRUSTED_CLIENT_CERTIFICATE_REQUIRED"] + CxPolicy[result] { settings := input.document[i].resource.google_sql_database_instance[name].settings @@ -17,7 +19,7 @@ CxPolicy[result] { "keyExpectedValue": "'settings.ip_configuration' should be defined and not null", "keyActualValue": "'settings.ip_configuration' is undefined or null", "searchLine": common_lib.build_search_line(["resource", "google_sql_database_instance", name],["settings"]), - "remediation": "ip_configuration {\n\t\trequire_ssl = true\n\t}\n", + "remediation": sprintf("ip_configuration {\n\t\tssl_mode = %s\n\t}\n", [get_remediation(input.document[i].resource.google_sql_database_instance[name].database_version)]), "remediationType": "addition", } } @@ -26,6 +28,7 @@ CxPolicy[result] { settings := input.document[i].resource.google_sql_database_instance[name].settings ip_configuration := settings.ip_configuration + not common_lib.valid_key(ip_configuration, "ssl_mode") not common_lib.valid_key(ip_configuration, "require_ssl") result := { @@ -34,15 +37,39 @@ CxPolicy[result] { "resourceName": tf_lib.get_resource_name(input.document[i].resource.google_sql_database_instance[name].settings, name), "searchKey": sprintf("google_sql_database_instance[%s].settings.ip_configuration", [name]), "issueType": "MissingAttribute", - "keyExpectedValue": "'settings.ip_configuration.require_ssl' should be defined and not null", - "keyActualValue": "'settings.ip_configuration.require_ssl' is undefined or null", + "keyExpectedValue": "'settings.ip_configuration.ssl_mode' should be defined and not null", + "keyActualValue": "'settings.ip_configuration.ssl_mode' is undefined or null", "searchLine": common_lib.build_search_line(["resource", "google_sql_database_instance", name],["settings", "ip_configuration"]), - "remediation": "require_ssl = true", + "remediation": sprintf("ssl_mode = %s", [get_remediation(input.document[i].resource.google_sql_database_instance[name].database_version)]), "remediationType": "addition", } } CxPolicy[result] { + resource := input.document[i].resource.google_sql_database_instance[name] + settings := resource.settings + + database_version := input.document[i].resource.google_sql_database_instance[name].database_version + kev := get_expected_key(database_version, settings.ip_configuration.ssl_mode) + + result := { + "documentId": input.document[i].id, + "resourceType": "google_sql_database_instance", + "resourceName": tf_lib.get_resource_name(input.document[i].resource.google_sql_database_instance[name].settings, name), + "searchKey": sprintf("google_sql_database_instance[%s].settings.ip_configuration.ssl_mode", [name]), + "issueType": "IncorrectValue", + "keyExpectedValue": sprintf("'settings.ip_configuration.ssl_mode' should be set to %s", [kev]), + "keyActualValue": sprintf("'settings.ip_configuration.ssl_mode' is set to '%s'", [settings.ip_configuration.ssl_mode]), + "searchLine": common_lib.build_search_line(["resource", "google_sql_database_instance", name],["settings", "ip_configuration", "ssl_mode"]), + "remediation": json.marshal({ + "before": settings.ip_configuration.ssl_mode, + "after": get_remediation(database_version) + }), + "remediationType": "replacement", + } +} + +CxPolicy[result] { # legacy support (terraform version < 6.0.1) settings := input.document[i].resource.google_sql_database_instance[name].settings settings.ip_configuration.require_ssl == false @@ -63,3 +90,14 @@ CxPolicy[result] { "remediationType": "replacement", } } + +get_expected_key(database_version, ssl_mode) = "'ENCRYPTED_ONLY'" { + contains(database_version, "SQLSERVER") + ssl_mode != "ENCRYPTED_ONLY" +} else = "'ENCRYPTED_ONLY' or 'TRUSTED_CLIENT_CERTIFICATE_REQUIRED'" { + not common_lib.inArray(allowed_ssl_modes, ssl_mode) +} + +get_remediation(database_version) = "ENCRYPTED_ONLY" { + contains(database_version, "SQLSERVER") +} else = "TRUSTED_CLIENT_CERTIFICATE_REQUIRED" \ No newline at end of file diff --git a/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/negative.tf b/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/negative1.tf similarity index 68% rename from assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/negative.tf rename to assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/negative1.tf index 5d30e0e42d8..895502bf918 100644 --- a/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/negative.tf +++ b/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/negative1.tf @@ -1,7 +1,8 @@ -resource "google_sql_database_instance" "negative1" { +resource "google_sql_database_instance" "negative1_1" { # legacy support (terraform version < 6.0.1) provider = google-beta name = "private-instance-${random_id.db_name_suffix.hex}" + database_version = "POSTGRES_15" region = "us-central1" depends_on = [google_service_networking_connection.private_vpc_connection] @@ -11,7 +12,7 @@ resource "google_sql_database_instance" "negative1" { ip_configuration { ipv4_enabled = false private_network = google_compute_network.private_network.id - require_ssl = true + require_ssl = true } } } \ No newline at end of file diff --git a/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/negative2.tf b/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/negative2.tf new file mode 100644 index 00000000000..3a5ee4f8061 --- /dev/null +++ b/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/negative2.tf @@ -0,0 +1,35 @@ +resource "google_sql_database_instance" "negative2_1" { + name = "private-instance-encrypted" + database_version = "POSTGRES_15" + region = "us-central1" + + depends_on = [google_service_networking_connection.private_vpc_connection] + + settings { + tier = "db-f1-micro" + + ip_configuration { + ipv4_enabled = false + private_network = google_compute_network.private_network.id + ssl_mode = "ENCRYPTED_ONLY" # Only allows connections encrypted with SSL/TLS + } + } +} + +resource "google_sql_database_instance" "negative2_2" { + name = "private-instance-trusted-cert" + database_version = "POSTGRES_15" + region = "us-central1" + + depends_on = [google_service_networking_connection.private_vpc_connection] + + settings { + tier = "db-f1-micro" + + ip_configuration { + ipv4_enabled = false + private_network = google_compute_network.private_network.id + ssl_mode = "TRUSTED_CLIENT_CERTIFICATE_REQUIRED" # Only allow connections encrypted with SSL/TLS and with valid client certificates + } + } +} \ No newline at end of file diff --git a/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/negative3.tf b/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/negative3.tf new file mode 100644 index 00000000000..ed69f09e2e4 --- /dev/null +++ b/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/negative3.tf @@ -0,0 +1,17 @@ +resource "google_sql_database_instance" "negative3_1" { + name = "private-instance-encrypted" + database_version = "SQLSERVER_2017_STANDARD" + region = "us-central1" + + depends_on = [google_service_networking_connection.private_vpc_connection] + + settings { + tier = "db-f1-micro" + + ip_configuration { + ipv4_enabled = false + private_network = google_compute_network.private_network.id + ssl_mode = "ENCRYPTED_ONLY" # Only allows connections encrypted with SSL/TLS + } + } +} \ No newline at end of file diff --git a/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/positive.tf b/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/positive1.tf similarity index 65% rename from assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/positive.tf rename to assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/positive1.tf index bc68849dc09..c02af49d0b7 100644 --- a/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/positive.tf +++ b/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/positive1.tf @@ -1,20 +1,22 @@ -resource "google_sql_database_instance" "positive1" { +resource "google_sql_database_instance" "positive1_1" { # legacy support (terraform version < 6.0.1) provider = google-beta name = "private-instance-${random_id.db_name_suffix.hex}" + database_version = "POSTGRES_15" region = "us-central1" depends_on = [google_service_networking_connection.private_vpc_connection] settings { - tier = "db-f1-micro" + tier = "db-f1-micro" # Undefined "ip_configuration" } } -resource "google_sql_database_instance" "positive2" { +resource "google_sql_database_instance" "positive1_2" { # legacy support (terraform version < 6.0.1) provider = google-beta name = "private-instance-${random_id.db_name_suffix.hex}" + database_version = "POSTGRES_15" region = "us-central1" depends_on = [google_service_networking_connection.private_vpc_connection] @@ -24,14 +26,16 @@ resource "google_sql_database_instance" "positive2" { ip_configuration { ipv4_enabled = false private_network = google_compute_network.private_network.id + # Undefined "require_ssl" } } } -resource "google_sql_database_instance" "positive3" { +resource "google_sql_database_instance" "positive1_3" { # legacy support (terraform version < 6.0.1) provider = google-beta name = "private-instance-${random_id.db_name_suffix.hex}" + database_version = "POSTGRES_15" region = "us-central1" depends_on = [google_service_networking_connection.private_vpc_connection] diff --git a/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/positive2.tf b/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/positive2.tf new file mode 100644 index 00000000000..e64fc2cd479 --- /dev/null +++ b/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/positive2.tf @@ -0,0 +1,54 @@ + +resource "google_sql_database_instance" "positive2_1" { + name = "private-instance-no-ssl-mode" + database_version = "POSTGRES_15" + region = "us-central1" + + depends_on = [google_service_networking_connection.private_vpc_connection] + + settings { + tier = "db-f1-micro" + + ip_configuration { + ipv4_enabled = false + private_network = google_compute_network.private_network.id + # Undefined "ssl_mode" + } + } +} + +resource "google_sql_database_instance" "positive2_2" { + name = "private-instance-unspecified" + database_version = "POSTGRES_15" + region = "us-central1" + + depends_on = [google_service_networking_connection.private_vpc_connection] + + settings { + tier = "db-f1-micro" + + ip_configuration { + ipv4_enabled = false + private_network = google_compute_network.private_network.id + ssl_mode = "SSL_MODE_UNSPECIFIED" # Unexpected value + } + } +} + +resource "google_sql_database_instance" "positive2_3" { + name = "private-instance-unencrypted" + database_version = "POSTGRES_15" + region = "us-central1" + + depends_on = [google_service_networking_connection.private_vpc_connection] + + settings { + tier = "db-f1-micro" + + ip_configuration { + ipv4_enabled = false + private_network = google_compute_network.private_network.id + ssl_mode = "ALLOW_UNENCRYPTED_AND_ENCRYPTED" # Allows unencrypted (non-SSL/non-TLS) connections + } + } +} \ No newline at end of file diff --git a/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/positive3.tf b/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/positive3.tf new file mode 100644 index 00000000000..590db8fec80 --- /dev/null +++ b/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/positive3.tf @@ -0,0 +1,85 @@ +resource "google_sql_database_instance" "positive3_1" { + provider = google-beta + + name = "private-instance-${random_id.db_name_suffix.hex}" + database_version = "POSTGRES_15" + region = "us-central1" + + depends_on = [google_service_networking_connection.private_vpc_connection] + + settings { + tier = "db-f1-micro" # Undefined "ip_configuration" + } +} + +resource "google_sql_database_instance" "positive3_2" { + name = "private-instance-no-ssl-mode" + database_version = "SQLSERVER_2017_STANDARD" + region = "us-central1" + + depends_on = [google_service_networking_connection.private_vpc_connection] + + settings { + tier = "db-f1-micro" + + ip_configuration { + ipv4_enabled = false + private_network = google_compute_network.private_network.id + # Undefined "ssl_mode" + } + } +} + +resource "google_sql_database_instance" "positive3_3" { + name = "private-instance-unspecified" + database_version = "SQLSERVER_2017_STANDARD" + region = "us-central1" + + depends_on = [google_service_networking_connection.private_vpc_connection] + + settings { + tier = "db-f1-micro" + + ip_configuration { + ipv4_enabled = false + private_network = google_compute_network.private_network.id + ssl_mode = "SSL_MODE_UNSPECIFIED" # Unexpected value + } + } +} + +resource "google_sql_database_instance" "positive3_4" { + name = "private-instance-unencrypted" + database_version = "SQLSERVER_2017_STANDARD" + region = "us-central1" + + depends_on = [google_service_networking_connection.private_vpc_connection] + + settings { + tier = "db-f1-micro" + + ip_configuration { + ipv4_enabled = false + private_network = google_compute_network.private_network.id + ssl_mode = "ALLOW_UNENCRYPTED_AND_ENCRYPTED" # Allows unencrypted (non-SSL/non-TLS) connections + } + } +} + +resource "google_sql_database_instance" "positive3_5" { + name = "private-instance-unspecified" + database_version = "SQLSERVER_2017_STANDARD" + region = "us-central1" + + depends_on = [google_service_networking_connection.private_vpc_connection] + + settings { + tier = "db-f1-micro" + + ip_configuration { + ipv4_enabled = false + private_network = google_compute_network.private_network.id + ssl_mode = "TRUSTED_CLIENT_CERTIFICATE_REQUIRED" # Value Unsupported by SQLSERVER databases + } + } +} \ No newline at end of file diff --git a/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/positive_expected_result.json b/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/positive_expected_result.json index 842962c52cb..37b62fa2980 100644 --- a/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/positive_expected_result.json +++ b/assets/queries/terraform/gcp/sql_db_instance_with_ssl_disabled/test/positive_expected_result.json @@ -2,16 +2,67 @@ { "queryName": "SQL DB Instance With SSL Disabled", "severity": "HIGH", - "line": 9 + "line": 10, + "fileName": "positive1.tf" }, { "queryName": "SQL DB Instance With SSL Disabled", "severity": "HIGH", - "line": 24 + "line": 26, + "fileName": "positive1.tf" }, { "queryName": "SQL DB Instance With SSL Disabled", "severity": "HIGH", - "line": 44 + "line": 48, + "fileName": "positive1.tf" + }, + { + "queryName": "SQL DB Instance With SSL Disabled", + "severity": "HIGH", + "line": 12, + "fileName": "positive2.tf" + }, + { + "queryName": "SQL DB Instance With SSL Disabled", + "severity": "HIGH", + "line": 33, + "fileName": "positive2.tf" + }, + { + "queryName": "SQL DB Instance With SSL Disabled", + "severity": "HIGH", + "line": 51, + "fileName": "positive2.tf" + }, + { + "queryName": "SQL DB Instance With SSL Disabled", + "severity": "HIGH", + "line": 10, + "fileName": "positive3.tf" + }, + { + "queryName": "SQL DB Instance With SSL Disabled", + "severity": "HIGH", + "line": 25, + "fileName": "positive3.tf" + }, + { + "queryName": "SQL DB Instance With SSL Disabled", + "severity": "HIGH", + "line": 46, + "fileName": "positive3.tf" + }, + { + "queryName": "SQL DB Instance With SSL Disabled", + "severity": "HIGH", + "line": 64, + "fileName": "positive3.tf" + }, + { + "queryName": "SQL DB Instance With SSL Disabled", + "severity": "HIGH", + "line": 82, + "fileName": "positive3.tf" } ]