diff --git a/examples/client-certificate/README.md b/examples/client-certificate/README.md new file mode 100644 index 0000000..b0467cc --- /dev/null +++ b/examples/client-certificate/README.md @@ -0,0 +1,22 @@ +# Client Certificate Example + +This folder contains an example of how to create client certificates for [Google Cloud SQL](https://cloud.google.com/sql/) database instance. +There can be only one pending operation at a given point of time because of the inherent Cloud SQL system architecture. +This is a limitation on the concurrent writes to a CloudSQL database. To resolve this issue, +we will create the certificate in a separate module. + +Creating the certificate while there are other operations ongoing will result in Avoiding `googleapi: Error 409: Operation failed because another operation was already in progress.` + + +## How do you run this example? + +To run this example, you need to: + +1. Install [Terraform](https://www.terraform.io/). +1. Open up `vars.tf` and set secrets at the top of the file as environment variables and fill in any other variables in + the file that don't have defaults. +1. `terraform init`. +1. `terraform plan`. +1. If the plan looks good, run `terraform apply`. + +When the templates are applied, Terraform will output the IP address of the instance and the instance path for [connecting using the Cloud SQL Proxy](https://cloud.google.com/sql/docs/mysql/connect-admin-proxy). diff --git a/examples/client-certificate/main.tf b/examples/client-certificate/main.tf new file mode 100644 index 0000000..c11d03e --- /dev/null +++ b/examples/client-certificate/main.tf @@ -0,0 +1,28 @@ +# ------------------------------------------------------------------------------ +# CREATE A CLIENT CERTIFICATE FOR CLOUD SQL DATABASE +# ------------------------------------------------------------------------------ + +# ------------------------------------------------------------------------------ +# CONFIGURE OUR GCP CONNECTION +# ------------------------------------------------------------------------------ + +provider "google-beta" { + region = "${var.region}" + project = "${var.project}" +} + +# Use Terraform 0.10.x so that we can take advantage of Terraform GCP functionality as a separate provider via +# https://github.com/terraform-providers/terraform-provider-google +terraform { + required_version = ">= 0.10.3" +} + +# ------------------------------------------------------------------------------ +# CREATE CLIENT CERTIFICATE +# ------------------------------------------------------------------------------ + +resource "google_sql_ssl_cert" "client_cert" { + provider = "google-beta" + common_name = "${var.common_name}" + instance = "${var.database_instance_name}" +} diff --git a/examples/client-certificate/outputs.tf b/examples/client-certificate/outputs.tf new file mode 100644 index 0000000..21dc370 --- /dev/null +++ b/examples/client-certificate/outputs.tf @@ -0,0 +1,10 @@ +output "client_ca_cert" { + description = "Certificate data for the client certificate." + value = "${google_sql_ssl_cert.client_cert.cert}" +} + +# In real-world cases, the output for the private key should always be encrypted +output "client_private_key" { + description = "Private key associated with the client certificate." + value = "${google_sql_ssl_cert.client_cert.private_key}" +} diff --git a/examples/client-certificate/variables.tf b/examples/client-certificate/variables.tf new file mode 100644 index 0000000..2c84a77 --- /dev/null +++ b/examples/client-certificate/variables.tf @@ -0,0 +1,21 @@ +# --------------------------------------------------------------------------------------------------------------------- +# REQUIRED PARAMETERS +# These variables are expected to be passed in by the operator +# --------------------------------------------------------------------------------------------------------------------- + +variable "project" { + description = "The project ID to host the database in." +} + +variable "region" { + description = "The region to host the database in." +} + +# Note, after a name db instance is used, it cannot be reused for up to one week. +variable "common_name" { + description = "The common name to be used in the certificate to identify the client. Constrained to [a-zA-Z.-_ ]+. Changing this forces a new resource to be created." +} + +variable "database_instance_name" { + description = "The name of the Cloud SQL instance. Changing this forces a new resource to be created." +} diff --git a/examples/mysql-private-ip/outputs.tf b/examples/mysql-private-ip/outputs.tf index 6f35f0f..3268020 100644 --- a/examples/mysql-private-ip/outputs.tf +++ b/examples/mysql-private-ip/outputs.tf @@ -1,21 +1,26 @@ -output "instance_name" { +output "master_instance_name" { description = "The name of the database instance" - value = "${module.mysql.instance_name}" + value = "${module.mysql.master_instance_name}" } -output "ip_addresses" { +output "master_ip_addresses" { description = "All IP addresses of the instance as list of maps, see https://www.terraform.io/docs/providers/google/r/sql_database_instance.html#ip_address-0-ip_address" - value = "${module.mysql.ip_addresses}" + value = "${module.mysql.master_ip_addresses}" } -output "private_ip" { +output "master_private_ip" { description = "The first IPv4 address of the addresses assigned to the instance. As this instance has only private IP, it is the private IP address." - value = "${module.mysql.first_ip_address}" + value = "${module.mysql.master_first_ip_address}" } -output "instance" { +output "master_instance" { description = "Self link to the master instance" - value = "${module.mysql.instance}" + value = "${module.mysql.master_instance}" +} + +output "master_proxy_connection" { + description = "Instance path for connecting with Cloud SQL Proxy. Read more at https://cloud.google.com/sql/docs/mysql/sql-proxy" + value = "${module.mysql.master_proxy_connection}" } output "db_name" { @@ -23,11 +28,6 @@ output "db_name" { value = "${module.mysql.db_name}" } -output "proxy_connection" { - description = "Instance path for connecting with Cloud SQL Proxy. Read more at https://cloud.google.com/sql/docs/mysql/sql-proxy" - value = "${module.mysql.proxy_connection}" -} - output "db" { description = "Self link to the default database" value = "${module.mysql.db}" diff --git a/examples/mysql-public-ip/main.tf b/examples/mysql-public-ip/main.tf index 62e01a0..1cc3067 100644 --- a/examples/mysql-public-ip/main.tf +++ b/examples/mysql-public-ip/main.tf @@ -62,6 +62,10 @@ module "mysql" { # addresses, and only allow access from specific trusted networks, servers or applications in your VPC. enable_public_internet_access = true + # Default setting for this is 'false' in 'variables.tf' + # In the test cases, we're setting this to true, to test forced SSL. + require_ssl = "${var.require_ssl}" + authorized_networks = [ { name = "allow-all-inbound" diff --git a/examples/mysql-public-ip/outputs.tf b/examples/mysql-public-ip/outputs.tf index d1ef2f5..95fc3ce 100644 --- a/examples/mysql-public-ip/outputs.tf +++ b/examples/mysql-public-ip/outputs.tf @@ -1,21 +1,31 @@ -output "instance_name" { +output "master_instance_name" { description = "The name of the database instance" - value = "${module.mysql.instance_name}" + value = "${module.mysql.master_instance_name}" } -output "ip_addresses" { +output "master_ip_addresses" { description = "All IP addresses of the instance as list of maps, see https://www.terraform.io/docs/providers/google/r/sql_database_instance.html#ip_address-0-ip_address" - value = "${module.mysql.ip_addresses}" + value = "${module.mysql.master_ip_addresses}" } -output "public_ip" { +output "master_public_ip" { description = "The first IPv4 address of the addresses assigned to the instance. As this instance has only public IP, it is the public IP address." - value = "${module.mysql.first_ip_address}" + value = "${module.mysql.master_first_ip_address}" } -output "instance" { +output "master_ca_cert" { + value = "${module.mysql.master_ca_cert}" + description = "The CA Certificate used to connect to the SQL Instance via SSL" +} + +output "master_instance" { description = "Self link to the master instance" - value = "${module.mysql.instance}" + value = "${module.mysql.master_instance}" +} + +output "master_proxy_connection" { + description = "Instance path for connecting with Cloud SQL Proxy. Read more at https://cloud.google.com/sql/docs/mysql/sql-proxy" + value = "${module.mysql.master_proxy_connection}" } output "db_name" { @@ -23,11 +33,6 @@ output "db_name" { value = "${module.mysql.db_name}" } -output "proxy_connection" { - description = "Instance path for connecting with Cloud SQL Proxy. Read more at https://cloud.google.com/sql/docs/mysql/sql-proxy" - value = "${module.mysql.proxy_connection}" -} - output "db" { description = "Self link to the default database" value = "${module.mysql.db}" diff --git a/examples/mysql-public-ip/variables.tf b/examples/mysql-public-ip/variables.tf index 0eecc43..d3e58c5 100644 --- a/examples/mysql-public-ip/variables.tf +++ b/examples/mysql-public-ip/variables.tf @@ -47,3 +47,10 @@ variable "name_override" { description = "You may optionally override the name_prefix + random string by specifying an override" default = "" } + +# When configuring a public IP instance, you should only allow secure connections +# For testing purposes, we're initially allowing unsecured connections. +variable "require_ssl" { + description = "True if the instance should require SSL/TLS for users connecting over IP. Note: SSL/TLS is needed to provide security when you connect to Cloud SQL using IP addresses. If you are connecting to your instance only by using the Cloud SQL Proxy or the Java Socket Library, you do not need to configure your instance to use SSL/TLS." + default = false +} diff --git a/modules/mysql/main.tf b/modules/mysql/main.tf index 465437b..38b4c1f 100644 --- a/modules/mysql/main.tf +++ b/modules/mysql/main.tf @@ -22,11 +22,13 @@ locals { authorized_networks = ["${var.authorized_networks}"] ipv4_enabled = "${var.enable_public_internet_access}" private_network = "${var.private_network}" + require_ssl = "${var.require_ssl}" }] "PUBLIC" = [{ authorized_networks = ["${var.authorized_networks}"] ipv4_enabled = "${var.enable_public_internet_access}" + require_ssl = "${var.require_ssl}" }] } @@ -123,3 +125,10 @@ resource "null_resource" "wait_for" { instance = "${var.wait_for}" } } + +# ------------------------------------------------------------------------------ +# CREATE A NULL RESOURCE TO SIGNAL ALL RESOURCES HAVE BEEN CREATED +# ------------------------------------------------------------------------------ +resource "null_resource" "complete" { + depends_on = ["google_sql_user.default"] +} diff --git a/modules/mysql/outputs.tf b/modules/mysql/outputs.tf index 7b199eb..d9d32f3 100644 --- a/modules/mysql/outputs.tf +++ b/modules/mysql/outputs.tf @@ -1,34 +1,64 @@ -output "instance_name" { +output "master_instance_name" { description = "The name of the database instance" value = "${google_sql_database_instance.master.name}" } -output "ip_addresses" { +output "master_ip_addresses" { description = "All IP addresses of the instance as list of maps, see https://www.terraform.io/docs/providers/google/r/sql_database_instance.html#ip_address-0-ip_address" value = "${ google_sql_database_instance.master.ip_address }" } -output "first_ip_address" { +output "master_first_ip_address" { description = "The first IPv4 address of the addresses assigned to the instance. If the instance has only public IP, it is the public IP address. If it has only private IP, it the private IP address. If it has both, it is the first item in the list and full IP address details are in 'instance_ip_addresses'" value = "${ google_sql_database_instance.master.first_ip_address }" } -output "instance" { +output "master_instance" { description = "Self link to the master instance" value = "${google_sql_database_instance.master.self_link}" } +output "master_proxy_connection" { + description = "Instance path for connecting with Cloud SQL Proxy. Read more at https://cloud.google.com/sql/docs/mysql/sql-proxy" + value = "${var.project}:${var.region}:${google_sql_database_instance.master.name}" +} + +output "master_ca_cert" { + value = "${google_sql_database_instance.master.server_ca_cert.0.cert}" + description = "The CA Certificate used to connect to the SQL Instance via SSL" +} + +output "master_ca_cert_common_name" { + value = "${google_sql_database_instance.master.server_ca_cert.0.common_name}" + description = "The CN valid for the CA Cert" +} + +output "master_ca_cert_create_time" { + value = "${google_sql_database_instance.master.server_ca_cert.0.create_time}" + description = "Creation time of the CA Cert" +} + +output "master_ca_cert_expiration_time" { + value = "${google_sql_database_instance.master.server_ca_cert.0.expiration_time}" + description = "Expiration time of the CA Cert" +} + +output "master_ca_cert_sha1_fingerprint" { + value = "${google_sql_database_instance.master.server_ca_cert.0.sha1_fingerprint}" + description = "SHA Fingerprint of the CA Cert" +} + +output "db" { + description = "Self link to the default database" + value = "${google_sql_database.default.self_link}" +} + output "db_name" { description = "Name of the default database" value = "${google_sql_database.default.name}" } -output "proxy_connection" { - description = "Instance path for connecting with Cloud SQL Proxy. Read more at https://cloud.google.com/sql/docs/mysql/sql-proxy" - value = "${var.project}:${var.region}:${google_sql_database_instance.master.name}" -} - -output "db" { - description = "Self link to the default database" - value = "${google_sql_database.default.self_link}" +output "complete" { + description = "Name of the default database" + value = "${null_resource.complete.id}" } diff --git a/modules/mysql/variables.tf b/modules/mysql/variables.tf index a1e1498..5ac690d 100644 --- a/modules/mysql/variables.tf +++ b/modules/mysql/variables.tf @@ -172,6 +172,11 @@ variable "enable_public_internet_access" { default = false } +variable "require_ssl" { + description = "True if the instance should require SSL/TLS for users connecting over IP. Note: SSL/TLS is needed to provide security when you connect to Cloud SQL using IP addresses. If you are connecting to your instance only by using the Cloud SQL Proxy or the Java Socket Library, you do not need to configure your instance to use SSL/TLS." + default = false +} + variable "private_network" { description = "The resource link for the VPC network from which the Cloud SQL instance is accessible for private IP." default = "" diff --git a/test/example_mysql_private_ip_test.go b/test/example_mysql_private_ip_test.go index 6d67fee..601c777 100644 --- a/test/example_mysql_private_ip_test.go +++ b/test/example_mysql_private_ip_test.go @@ -54,15 +54,15 @@ func TestMySqlPrivateIP(t *testing.T) { region := test_structure.LoadString(t, exampleDir, KEY_REGION) projectId := test_structure.LoadString(t, exampleDir, KEY_PROJECT) - instanceNameFromOutput := terraform.Output(t, terraformOptions, OUTPUT_INSTANCE_NAME) - ipAddressesFromOutput := terraform.Output(t, terraformOptions, OUTPUT_IP_ADDRESSES) - privateIPFromOutput := terraform.Output(t, terraformOptions, OUTPUT_PRIVATE_IP) + instanceNameFromOutput := terraform.Output(t, terraformOptions, OUTPUT_MASTER_INSTANCE_NAME) + ipAddressesFromOutput := terraform.Output(t, terraformOptions, OUTPUT_MASTER_IP_ADDRESSES) + privateIPFromOutput := terraform.Output(t, terraformOptions, OUTPUT_MASTER_PRIVATE_IP) assert.Contains(t, ipAddressesFromOutput, "PRIVATE", "IP Addresses output has to contain 'PRIVATE'") assert.Contains(t, ipAddressesFromOutput, privateIPFromOutput, "IP Addresses output has to contain 'private_ip' from output") dbNameFromOutput := terraform.Output(t, terraformOptions, OUTPUT_DB_NAME) - proxyConnectionFromOutput := terraform.Output(t, terraformOptions, OUTPUT_PROXY_CONNECTION) + proxyConnectionFromOutput := terraform.Output(t, terraformOptions, OUTPUT_MASTER_PROXY_CONNECTION) expectedDBConn := fmt.Sprintf("%s:%s:%s", projectId, region, instanceNameFromOutput) diff --git a/test/example_mysql_public_ip_test.go b/test/example_mysql_public_ip_test.go index 5527d58..cea3582 100644 --- a/test/example_mysql_public_ip_test.go +++ b/test/example_mysql_public_ip_test.go @@ -1,10 +1,12 @@ package test import ( + "crypto/tls" + "crypto/x509" "database/sql" "fmt" - "github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/dialers/mysql" - _ "github.com/go-sql-driver/mysql" + mydialer "github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/dialers/mysql" + "github.com/go-sql-driver/mysql" "github.com/gruntwork-io/terratest/modules/gcp" "github.com/gruntwork-io/terratest/modules/logger" "github.com/gruntwork-io/terratest/modules/terraform" @@ -19,6 +21,7 @@ import ( const NAME_PREFIX_PUBLIC = "mysql-public" const EXAMPLE_NAME_PUBLIC = "mysql-public-ip" +const EXAMPLE_NAME_CERT = "client-certificate" func TestMySqlPublicIP(t *testing.T) { t.Parallel() @@ -28,10 +31,15 @@ func TestMySqlPublicIP(t *testing.T) { //os.Setenv("SKIP_validate_outputs", "true") //os.Setenv("SKIP_sql_tests", "true") //os.Setenv("SKIP_proxy_tests", "true") + //os.Setenv("SKIP_deploy_cert", "true") + //os.Setenv("SKIP_redeploy", "true") + //os.Setenv("SKIP_ssl_sql_tests", "true") + //os.Setenv("SKIP_teardown_cert", "true") //os.Setenv("SKIP_teardown", "true") _examplesDir := test_structure.CopyTerraformFolderToTemp(t, "../", "examples") exampleDir := filepath.Join(_examplesDir, EXAMPLE_NAME_PUBLIC) + certExampleDir := filepath.Join(_examplesDir, EXAMPLE_NAME_CERT) // BOOTSTRAP VARIABLES FOR THE TESTS test_structure.RunTestStage(t, "bootstrap", func() { @@ -49,6 +57,11 @@ func TestMySqlPublicIP(t *testing.T) { terraform.Destroy(t, terraformOptions) }) + defer test_structure.RunTestStage(t, "teardown_cert", func() { + terraformOptions := test_structure.LoadTerraformOptions(t, certExampleDir) + terraform.Destroy(t, terraformOptions) + }) + test_structure.RunTestStage(t, "deploy", func() { region := test_structure.LoadString(t, exampleDir, KEY_REGION) projectId := test_structure.LoadString(t, exampleDir, KEY_PROJECT) @@ -65,9 +78,9 @@ func TestMySqlPublicIP(t *testing.T) { region := test_structure.LoadString(t, exampleDir, KEY_REGION) projectId := test_structure.LoadString(t, exampleDir, KEY_PROJECT) - instanceNameFromOutput := terraform.Output(t, terraformOptions, OUTPUT_INSTANCE_NAME) + instanceNameFromOutput := terraform.Output(t, terraformOptions, OUTPUT_MASTER_INSTANCE_NAME) dbNameFromOutput := terraform.Output(t, terraformOptions, OUTPUT_DB_NAME) - proxyConnectionFromOutput := terraform.Output(t, terraformOptions, OUTPUT_PROXY_CONNECTION) + proxyConnectionFromOutput := terraform.Output(t, terraformOptions, OUTPUT_MASTER_PROXY_CONNECTION) expectedDBConn := fmt.Sprintf("%s:%s:%s", projectId, region, instanceNameFromOutput) @@ -80,7 +93,7 @@ func TestMySqlPublicIP(t *testing.T) { test_structure.RunTestStage(t, "sql_tests", func() { terraformOptions := test_structure.LoadTerraformOptions(t, exampleDir) - publicIp := terraform.Output(t, terraformOptions, OUTPUT_PUBLIC_IP) + publicIp := terraform.Output(t, terraformOptions, OUTPUT_MASTER_PUBLIC_IP) connectionString := fmt.Sprintf("%s:%s@tcp(%s:3306)/%s", DB_USER, DB_PASS, publicIp, DB_NAME) @@ -132,13 +145,13 @@ func TestMySqlPublicIP(t *testing.T) { test_structure.RunTestStage(t, "proxy_tests", func() { terraformOptions := test_structure.LoadTerraformOptions(t, exampleDir) - proxyConn := terraform.Output(t, terraformOptions, OUTPUT_PROXY_CONNECTION) + proxyConn := terraform.Output(t, terraformOptions, OUTPUT_MASTER_PROXY_CONNECTION) logger.Logf(t, "Connecting to: %s via Cloud SQL Proxy", proxyConn) // Use the Cloud SQL Proxy for queries // See https://cloud.google.com/sql/docs/mysql/sql-proxy - cfg := mysql.Cfg(proxyConn, DB_USER, DB_PASS) + cfg := mydialer.Cfg(proxyConn, DB_USER, DB_PASS) cfg.DBName = DB_NAME cfg.ParseTime = true @@ -148,7 +161,7 @@ func TestMySqlPublicIP(t *testing.T) { cfg.WriteTimeout = timeout // Dial in. This one actually pings the database already - db, err := mysql.DialCfg(cfg) + db, err := mydialer.DialCfg(cfg) require.NoError(t, err, "Failed to open Proxy DB connection") // Make sure we clean up properly @@ -176,4 +189,98 @@ func TestMySqlPublicIP(t *testing.T) { // Since we set the auto increment to 5, modulus should always be 0 assert.Equal(t, int64(0), int64(lastId%5)) }) + + // CREATE CLIENT CERT + test_structure.RunTestStage(t, "deploy_cert", func() { + region := test_structure.LoadString(t, exampleDir, KEY_REGION) + projectId := test_structure.LoadString(t, exampleDir, KEY_PROJECT) + + terraformOptions := test_structure.LoadTerraformOptions(t, exampleDir) + instanceNameFromOutput := terraform.Output(t, terraformOptions, OUTPUT_MASTER_INSTANCE_NAME) + commonName := fmt.Sprintf("%s-client", instanceNameFromOutput) + + terraformOptionsForCert := createTerratestOptionsForClientCert(projectId, region, certExampleDir, commonName, instanceNameFromOutput) + test_structure.SaveTerraformOptions(t, certExampleDir, terraformOptionsForCert) + + terraform.InitAndApply(t, terraformOptionsForCert) + }) + + // REDEPLOY WITH FORCED SSL SETTINGS + test_structure.RunTestStage(t, "redeploy", func() { + terraformOptions := test_structure.LoadTerraformOptions(t, exampleDir) + + // Force secure connections + terraformOptions.Vars["require_ssl"] = true + terraform.InitAndApply(t, terraformOptions) + }) + + // RUN TESTS WITH SECURED CONNECTION + test_structure.RunTestStage(t, "ssl_sql_tests", func() { + terraformOptions := test_structure.LoadTerraformOptions(t, exampleDir) + terraformOptionsForCert := test_structure.LoadTerraformOptions(t, certExampleDir) + + //******************************************************** + // First test that we're not allowed to connect over insecure connection + //******************************************************** + + publicIp := terraform.Output(t, terraformOptions, OUTPUT_MASTER_PUBLIC_IP) + + connectionString := fmt.Sprintf("%s:%s@tcp(%s:3306)/%s", DB_USER, DB_PASS, publicIp, DB_NAME) + + // Does not actually open up the connection - just returns a DB ref + logger.Logf(t, "Connecting to: %s", publicIp) + db, err := sql.Open("mysql", + connectionString) + require.NoError(t, err, "Failed to open DB connection") + + // Make sure we clean up properly + defer db.Close() + + // Run ping to actually test the connection + logger.Log(t, "Ping the DB with forced SSL") + if err = db.Ping(); err != nil { + logger.Logf(t, "Not allowed to ping %s as expected.", publicIp) + } else { + t.Fatalf("Ping %v succeeded against the odds.", publicIp) + } + + //******************************************************** + // Test connection over secure connection + //******************************************************** + + // Prepare certificates + rootCertPool := x509.NewCertPool() + serverCertB := []byte(terraform.Output(t, terraformOptions, OUTPUT_MASTER_CA_CERT)) + clientCertB := []byte(terraform.Output(t, terraformOptionsForCert, OUTPUT_CLIENT_CA_CERT)) + clientPKB := []byte(terraform.Output(t, terraformOptionsForCert, OUTPUT_CLIENT_PRIVATE_KEY)) + + if ok := rootCertPool.AppendCertsFromPEM(serverCertB); !ok { + t.Fatal("Failed to append PEM.") + } + + clientCert := make([]tls.Certificate, 0, 1) + certs, err := tls.X509KeyPair(clientCertB, clientPKB) + require.NoError(t, err, "Failed to create key pair") + + clientCert = append(clientCert, certs) + + // Register MySQL certificate config + // To avoid certificate validation errors complaining about + // missing IP SANs, we set 'InsecureSkipVerify: true' + mysql.RegisterTLSConfig("custom", &tls.Config{ + RootCAs: rootCertPool, + Certificates: clientCert, + InsecureSkipVerify: true, + }) + + // Prepare the secure connection string and ping the DB + sslConnectionString := fmt.Sprintf("%s:%s@tcp(%s:3306)/%s?tls=custom", DB_USER, DB_PASS, publicIp, DB_NAME) + db, err = sql.Open("mysql", sslConnectionString) + + // Run ping to actually test the connection with the SSL config + logger.Log(t, "Ping the DB with forced SSL") + if err = db.Ping(); err != nil { + t.Fatalf("Failed to ping DB with forced SSL: %v", err) + } + }) } diff --git a/test/test_util.go b/test/test_util.go index 220e4c8..d002fa5 100644 --- a/test/test_util.go +++ b/test/test_util.go @@ -15,12 +15,16 @@ const KEY_PROJECT = "project" const MYSQL_VERSION = "MYSQL_5_7" -const OUTPUT_IP_ADDRESSES = "ip_addresses" -const OUTPUT_INSTANCE_NAME = "instance_name" -const OUTPUT_PROXY_CONNECTION = "proxy_connection" +const OUTPUT_MASTER_IP_ADDRESSES = "master_ip_addresses" +const OUTPUT_MASTER_INSTANCE_NAME = "master_instance_name" +const OUTPUT_MASTER_PROXY_CONNECTION = "master_proxy_connection" +const OUTPUT_MASTER_PUBLIC_IP = "master_public_ip" +const OUTPUT_MASTER_PRIVATE_IP = "master_private_ip" +const OUTPUT_MASTER_CA_CERT = "master_ca_cert" +const OUTPUT_CLIENT_CA_CERT = "client_ca_cert" +const OUTPUT_CLIENT_PRIVATE_KEY = "client_private_key" + const OUTPUT_DB_NAME = "db_name" -const OUTPUT_PUBLIC_IP = "public_ip" -const OUTPUT_PRIVATE_IP = "private_ip" const MYSQL_CREATE_TEST_TABLE_WITH_AUTO_INCREMENT_STATEMENT = "CREATE TABLE IF NOT EXISTS test (id int NOT NULL AUTO_INCREMENT, name varchar(10) NOT NULL, PRIMARY KEY (ID))" const MYSQL_EMPTY_TEST_TABLE_STATEMENT = "DELETE FROM test" @@ -50,3 +54,19 @@ func createTerratestOptionsForMySql(projectId string, region string, exampleDir return terratestOptions } + +func createTerratestOptionsForClientCert(projectId string, region string, exampleDir string, commonName string, instanceName string) *terraform.Options { + + terratestOptions := &terraform.Options{ + // The path to where your Terraform code is located + TerraformDir: exampleDir, + Vars: map[string]interface{}{ + "region": region, + "project": projectId, + "common_name": commonName, + "database_instance_name": instanceName, + }, + } + + return terratestOptions +}