|
1 | 1 | package datastream_test
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "fmt" |
4 | 5 | "testing"
|
| 6 | + "time" |
5 | 7 |
|
6 | 8 | "github.com/hashicorp/terraform-plugin-testing/helper/resource"
|
7 | 9 | "github.com/hashicorp/terraform-provider-google/google/acctest"
|
@@ -76,6 +78,114 @@ func TestAccDatastreamConnectionProfile_update(t *testing.T) {
|
76 | 78 | })
|
77 | 79 | }
|
78 | 80 |
|
| 81 | +func TestAccDatastreamConnectionProfile_sshKey_update(t *testing.T) { |
| 82 | + t.Parallel() |
| 83 | + |
| 84 | + context := map[string]interface{}{ |
| 85 | + "random_suffix": acctest.RandString(t, 10), |
| 86 | + } |
| 87 | + |
| 88 | + randomPubKey1 := `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCjXhptfWIrtflLZ1WeOsjCfHSEKvui0fdNXTqpqIA+2NNlFjwKS4mV3bDJIRlC5FdWG/D5LW4kvSmcTx1eSLUcvqw3i3F73Ii35AR1Rid1bY0LCBYUUgkDKyvZgDzrM7g+MwBtthoud8Axt9/bh28qtzSVNvWfxIYsa2CwtqlkZr5c6Qb6N2B9kxW8WFsCnoAeBaZDMq+LVBRsRJvBBrJm/qhMNPd07Al7wGLEnNPWmwjFT7B12sMjNr7ZNLfI9VckEyUSx3AGBFH7RImeYiWb6vZA9v5DE7kBrCoHtJK5IN9dvqEWXrrDT7RTFXd55xQqT70eZiIDNz1nexDw8ZCn user` |
| 89 | + randomPrivKey1 := `-----BEGIN OPENSSH PRIVATE KEY----- |
| 90 | +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn |
| 91 | +NhAAAAAwEAAQAAAQEAo14abX1iK7X5S2dVnjrIwnx0hCr7otH3TV06qaiAPtjTZRY8CkuJ |
| 92 | +ld2wySEZQuRXVhvw+S1uJL0pnE8dXki1HL6sN4txe9yIt+QEdUYndW2NCwgWFFIJAysr2Y |
| 93 | +A86zO4PjMAbbYaLnfAMbff24dvKrc0lTb1n8SGLGtgsLapZGa+XOkG+jdgfZMVvFhbAp6A |
| 94 | +HgWmQzKvi1QUbESbwQayZv6oTDT3dOwJe8BixJzT1psIxU+wddrDIza+2TS3yPVXJBMlEs |
| 95 | +dwBgRR+0SJnmIlm+r2QPb+QxO5AawqB7SSuSDfXb6hFl66w0+0UxV3eecUKk+9HmYiAzc9 |
| 96 | +Z3sQ8PGQpwAAA8B2IBoLdiAaCwAAAAdzc2gtcnNhAAABAQCjXhptfWIrtflLZ1WeOsjCfH |
| 97 | +SEKvui0fdNXTqpqIA+2NNlFjwKS4mV3bDJIRlC5FdWG/D5LW4kvSmcTx1eSLUcvqw3i3F7 |
| 98 | +3Ii35AR1Rid1bY0LCBYUUgkDKyvZgDzrM7g+MwBtthoud8Axt9/bh28qtzSVNvWfxIYsa2 |
| 99 | +CwtqlkZr5c6Qb6N2B9kxW8WFsCnoAeBaZDMq+LVBRsRJvBBrJm/qhMNPd07Al7wGLEnNPW |
| 100 | +mwjFT7B12sMjNr7ZNLfI9VckEyUSx3AGBFH7RImeYiWb6vZA9v5DE7kBrCoHtJK5IN9dvq |
| 101 | +EWXrrDT7RTFXd55xQqT70eZiIDNz1nexDw8ZCnAAAAAwEAAQAAAQAnvU5kb+mfhGaeBwb2 |
| 102 | +tIn9dVTKicIoezbTJOiOOKTppMjXgC8euf0/7WuBoYGJmg38rlNR6dEvMqyaj0wvkTQtR9 |
| 103 | +yQrmTuoljHkrna5TPYBswWcOMeEk6K7Md/4wfulugsiS+DgJah0xN3hKj5t9o848/wtCvP |
| 104 | +r3iL+ZrNocFW4Ju+QrArFWTLFuJL4uc69ykgWE7I5Qkm+3Lg6aSoNazMzCu9rCblduetJq |
| 105 | +EilQ6AOkv68xTOQ1EDIQc8xr6u6GCUvVVBwYaR3cYV6fWeLWJATqUODkEXdDZfgUerf4Io |
| 106 | +3KirdRf0YFyJiHJh4AqWd76jWCkhCwrREx0lfMCZghoxAAAAgHwOfMJtd4wOug2BPKu0SA |
| 107 | +HSwQ+yTTibg2xuENstd8akJC3VsU5GC8pngNAyoFpSt3QDlLpvqPqXVJSkkMbUtnPO0SIR |
| 108 | +5ffMB97kFvNkMNDUIalwxR9DV1CMPTAnTO7NSfO8UUKRjKivpmpS6ptMjxUM0hPoDBebhx |
| 109 | +P37In1a2jDAAAAgQDVCaoMFjHRGds1JaVjm6YviR0C2OsE55GOS7cW+I3SE63DumfHsN8i |
| 110 | +r/u5oEQUelaauYVmi9tT3L4lReFX2tYqtyE0mbPUXcY5XfmBxBsjW1sQ6YyHlN/vGLgo33 |
| 111 | +NZZFpIg2FknTzM4qeddfbyKuqAJX27f7RrSZCf+WrJUKDWqwAAAIEAxFAn6d9na7uHnb31 |
| 112 | +TQ8PoTvkH7fwugXuG7ACLCTl3PpOSGPQAPI8rCaGOMd+uU1Jyjt3TcdPYlNAtiFQCxWLMH |
| 113 | +RNFfeqviC85H6WzQNezNj45QqKTf5gRdHVu2NMRwn2pJjRgdIvsUaL1AY4sC0AivoEMlpx |
| 114 | +rQYvdaDG7KsYXfUAAAAEdXNlcgECAwQFBgc= |
| 115 | +-----END OPENSSH PRIVATE KEY-----` |
| 116 | + |
| 117 | + randomPubKey2 := `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDmc1i/FqnVtYsTzb6LmoUGom8ISnfRCPTIFf3LLIyRFgO+qD6Dnqn5p2lLE8ksdooAGJ+EyJtV5c+3kYGnjzzH4TlB2pkt562BntrggvJ98sELQbHEDiemiLnJqqIESk5FcSXdcJ/UX/AdkbXLjSR5M8+cGGqKSb0HSnKfOWkjWwZwp/JwbvyWPIJ6IQNKzAS5HVU/J+u8ezhPd1iBdezvAuPlihpjMGQg1KW3APZoELS6/BSMpXcvDy+TwuggEPPZ0Up09BJRtqesHiZur6CnqUIzJcCWCfi5C8IfHzlhawry+iA1V5Lh06Mz7OaySXpf902RITfh+KcLxcSSMmPl user` |
| 118 | + randomPrivKey2 := `-----BEGIN OPENSSH PRIVATE KEY----- |
| 119 | +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn |
| 120 | +NhAAAAAwEAAQAAAQEA5nNYvxap1bWLE82+i5qFBqJvCEp30Qj0yBX9yyyMkRYDvqg+g56p |
| 121 | ++adpSxPJLHaKABifhMibVeXPt5GBp488x+E5QdqZLeetgZ7a4ILyffLBC0GxxA4npoi5ya |
| 122 | +qiBEpORXEl3XCf1F/wHZG1y40keTPPnBhqikm9B0pynzlpI1sGcKfycG78ljyCeiEDSswE |
| 123 | +uR1VPyfrvHs4T3dYgXXs7wLj5YoaYzBkINSltwD2aBC0uvwUjKV3Lw8vk8LoIBDz2dFKdP |
| 124 | +QSUbanrB4mbq+gp6lCMyXAlgn4uQvCHx85YWsK8vogNVeS4dOjM+zmskl6X/dNkSE34fin |
| 125 | +C8XEkjJj5QAAA8CppfYQqaX2EAAAAAdzc2gtcnNhAAABAQDmc1i/FqnVtYsTzb6LmoUGom |
| 126 | +8ISnfRCPTIFf3LLIyRFgO+qD6Dnqn5p2lLE8ksdooAGJ+EyJtV5c+3kYGnjzzH4TlB2pkt |
| 127 | +562BntrggvJ98sELQbHEDiemiLnJqqIESk5FcSXdcJ/UX/AdkbXLjSR5M8+cGGqKSb0HSn |
| 128 | +KfOWkjWwZwp/JwbvyWPIJ6IQNKzAS5HVU/J+u8ezhPd1iBdezvAuPlihpjMGQg1KW3APZo |
| 129 | +ELS6/BSMpXcvDy+TwuggEPPZ0Up09BJRtqesHiZur6CnqUIzJcCWCfi5C8IfHzlhawry+i |
| 130 | +A1V5Lh06Mz7OaySXpf902RITfh+KcLxcSSMmPlAAAAAwEAAQAAAQEAq2opHRpSgfBj3vsv |
| 131 | +PNBXGrRAOr6JmSc8TIhvG22rsU/awTqMJYMjk9v+6iVxgm06ARBPt4kwYhhrBXRqKKTW5S |
| 132 | +aWXHGpdwfZe40Z6d39Wcnz5debzuVogOs6ptMRaHeM+QJM1AYuHN6v0I7N1vbJpo3vY4CV |
| 133 | +3v8yZ/XshJtDpVNqHFuCh1r07aW4NlqoTy5TEvWD1VPCqAVwTLWuNMfWRGYbwqJrRUxuu3 |
| 134 | +6vqddE8yMONYMwVRKPADj0DTi3i+LK3v6QfJlxb09EhqJPOOXM+fBVzUWkUXlPjvMP4uUH |
| 135 | +/zRrGscSI93n0V/H3/XTOJTskdEZUEFpeFbUXIphloCKEQAAAIEA9CJapVXG9HcKimXX3I |
| 136 | +OQdwPoKONM52KnAoWjGO1N5ECydjz2yHQkNJNLFwAUefmKVy0/ce0EdyEJjoHKvCwoTWL6 |
| 137 | +3CPlWQY+7pk0Fr62iT7UjjGwCtmHB6B5G4qUlsBkVN3WCwfmBwYrziRR+qcS8hSS7m37Uy |
| 138 | +rMbGGIHHVGPzIAAACBAP6ouUUlIN7jLdLxyApj1Cx7oW7Gp33j3goXn82WVv6+ubPJymVD |
| 139 | +u7zmoWWVegOngoPlR1q/mHBGoB1Ec1Im5IaN5qzVrxVKraJz5Q1XRc/azpkYb1FaDFBW2O |
| 140 | +iDaP5PHvNQpYcmE82Dg8bUqa7tYIUgq2vqHJdBZC5IvnYnGrWbAAAAgQDnqf2DVITbK5jK |
| 141 | +UJqEmni0YE8PD3PuPGRWLmZeOcxshHR1nQIeUoXWAhCS9G7Rl5Kdr1IXzSln22OvUXMPmE |
| 142 | +gZLd7QJVyRQ0bXhYf8nIs/UGhjq83OSoS4iSwHeZ1CrKWmVP74/+Na6fDdfJ65Z8+I4ktM |
| 143 | +QC3v6moZVb2wrgGkfwAAAAR1c2VyAQIDBAU= |
| 144 | +-----END OPENSSH PRIVATE KEY-----` |
| 145 | + |
| 146 | + acctest.VcrTest(t, resource.TestCase{ |
| 147 | + PreCheck: func() { acctest.AccTestPreCheck(t) }, |
| 148 | + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), |
| 149 | + ExternalProviders: map[string]resource.ExternalProvider{ |
| 150 | + "time": { |
| 151 | + Source: "registry.terraform.io/hashicorp/time", |
| 152 | + }, |
| 153 | + }, |
| 154 | + CheckDestroy: testAccCheckDatastreamConnectionProfileDestroyProducer(t), |
| 155 | + Steps: []resource.TestStep{ |
| 156 | + { |
| 157 | + Config: testAccDatastreamConnectionProfile_sshKey_update(context, true, randomPrivKey1, randomPubKey1), |
| 158 | + }, |
| 159 | + { |
| 160 | + ResourceName: "google_datastream_connection_profile.ssh_connectivity_profile", |
| 161 | + ImportState: true, |
| 162 | + ImportStateVerify: true, |
| 163 | + ImportStateVerifyIgnore: []string{"connection_profile_id", "location", "create_without_validation", "forward_ssh_connectivity.0.private_key", "postgresql_profile.0.password"}, |
| 164 | + }, |
| 165 | + { |
| 166 | + PreConfig: func() { |
| 167 | + fmt.Println("Waiting before proceeding to the next step...") |
| 168 | + time.Sleep(150 * time.Second) // Delay before the next step |
| 169 | + }, |
| 170 | + Config: testAccDatastreamConnectionProfile_sshKey_update(context, true, randomPrivKey2, randomPubKey2), |
| 171 | + }, |
| 172 | + { |
| 173 | + ResourceName: "google_datastream_connection_profile.ssh_connectivity_profile", |
| 174 | + ImportState: true, |
| 175 | + ImportStateVerify: true, |
| 176 | + ImportStateVerifyIgnore: []string{"connection_profile_id", "location", "create_without_validation", "forward_ssh_connectivity.0.private_key", "postgresql_profile.0.password"}, |
| 177 | + }, |
| 178 | + { |
| 179 | + PreConfig: func() { |
| 180 | + fmt.Println("Waiting before proceeding to the next step...") |
| 181 | + time.Sleep(150 * time.Second) // Delay before the next step |
| 182 | + }, |
| 183 | + Config: testAccDatastreamConnectionProfile_sshKey_update(context, false, randomPrivKey2, randomPubKey2), |
| 184 | + }, |
| 185 | + }, |
| 186 | + }) |
| 187 | +} |
| 188 | + |
79 | 189 | func testAccDatastreamConnectionProfile_update(context map[string]interface{}) string {
|
80 | 190 | return acctest.Nprintf(`
|
81 | 191 | resource "google_datastream_connection_profile" "default" {
|
@@ -247,3 +357,157 @@ resource "google_datastream_connection_profile" "mysql_con_profile" {
|
247 | 357 | }
|
248 | 358 | `, context)
|
249 | 359 | }
|
| 360 | + |
| 361 | +func testAccDatastreamConnectionProfile_sshKey_update(context map[string]interface{}, preventDestroy bool, private_key string, public_key string) string { |
| 362 | + context["lifecycle_block"] = "" |
| 363 | + if preventDestroy { |
| 364 | + context["lifecycle_block"] = ` |
| 365 | + lifecycle { |
| 366 | + prevent_destroy = true |
| 367 | + }` |
| 368 | + } |
| 369 | + context["private_key"] = private_key |
| 370 | + context["public_key"] = public_key |
| 371 | + |
| 372 | + return acctest.Nprintf(` |
| 373 | +resource "google_compute_network" "default" { |
| 374 | + name = "tf-test-datastream-ssh%{random_suffix}" |
| 375 | +} |
| 376 | +
|
| 377 | +resource "google_sql_database_instance" "instance" { |
| 378 | + depends_on = [google_compute_instance.default] |
| 379 | + name = "tf-test-my-database-instance%{random_suffix}" |
| 380 | + database_version = "POSTGRES_14" |
| 381 | + region = "us-central1" |
| 382 | + settings { |
| 383 | + tier = "db-f1-micro" |
| 384 | + ip_configuration { |
| 385 | + ipv4_enabled = true |
| 386 | +
|
| 387 | + authorized_networks { |
| 388 | + value = google_compute_instance.default.network_interface.0.access_config.0.nat_ip |
| 389 | + } |
| 390 | + } |
| 391 | + } |
| 392 | + |
| 393 | + deletion_protection = "false" |
| 394 | +} |
| 395 | +
|
| 396 | +resource "google_sql_database" "db" { |
| 397 | + depends_on = [google_sql_database_instance.instance] |
| 398 | + instance = google_sql_database_instance.instance.name |
| 399 | + name = "db" |
| 400 | +} |
| 401 | +
|
| 402 | +resource "google_sql_user" "user" { |
| 403 | + depends_on = [google_sql_database_instance.instance] |
| 404 | + name = "user" |
| 405 | + instance = google_sql_database_instance.instance.name |
| 406 | + password = "password%{random_suffix}" |
| 407 | +} |
| 408 | +
|
| 409 | +resource "google_compute_instance" "default" { |
| 410 | + name = "tf-test-instance-%{random_suffix}" |
| 411 | + machine_type = "e2-small" |
| 412 | + zone = "us-central1-a" |
| 413 | + boot_disk { |
| 414 | + initialize_params { |
| 415 | + image = "debian-11-bullseye-v20241009" |
| 416 | + } |
| 417 | + } |
| 418 | +
|
| 419 | + network_interface { |
| 420 | + network = google_compute_network.default.name |
| 421 | + access_config {} |
| 422 | + } |
| 423 | +
|
| 424 | + metadata = { |
| 425 | + "ssh-keys" = "user:%{public_key}" |
| 426 | + } |
| 427 | +
|
| 428 | + metadata_startup_script = <<-EOT |
| 429 | + #!/bin/bash |
| 430 | + echo "Updating SSHD config for SSH forwarding..." |
| 431 | +
|
| 432 | + # Backup sshd_config |
| 433 | + echo "AllowTcpForwarding yes" >> /etc/ssh/sshd_config |
| 434 | + echo "PasswordAuthentication no" >> /etc/ssh/sshd_config |
| 435 | + echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config |
| 436 | + echo "AuthorizedKeysFile .ssh/authorized_keys" >> /etc/ssh/sshd_config |
| 437 | + |
| 438 | + # Restart SSH service |
| 439 | + systemctl restart sshd |
| 440 | + EOT |
| 441 | +
|
| 442 | + tags = ["ssh-host"] |
| 443 | +
|
| 444 | + depends_on = [google_compute_firewall.ssh, google_compute_firewall.datastream_sql_access] |
| 445 | +
|
| 446 | +} |
| 447 | +
|
| 448 | +resource "time_sleep" "ssh_host_wait" { |
| 449 | + depends_on = [google_compute_instance.default] |
| 450 | + create_duration = "12m" |
| 451 | +} |
| 452 | +
|
| 453 | +resource "google_compute_firewall" "ssh" { |
| 454 | + name = "tf-test-%{random_suffix}" |
| 455 | + network = google_compute_network.default.name |
| 456 | +
|
| 457 | + allow { |
| 458 | + protocol = "tcp" |
| 459 | + ports = ["22"] |
| 460 | + } |
| 461 | +
|
| 462 | + direction = "INGRESS" |
| 463 | + priority = 1000 |
| 464 | + source_ranges = ["34.71.242.81", "34.72.28.29", "34.67.6.157", "34.67.234.134", "34.72.239.218"] |
| 465 | +
|
| 466 | + target_tags = ["ssh-host"] |
| 467 | +} |
| 468 | +
|
| 469 | +resource "google_compute_firewall" "datastream_sql_access" { |
| 470 | + name = "datastream-to-cloudsql-%{random_suffix}" |
| 471 | + network = google_compute_network.default.name |
| 472 | +
|
| 473 | + allow { |
| 474 | + protocol = "tcp" |
| 475 | + ports = ["5432"] |
| 476 | + } |
| 477 | +
|
| 478 | + direction = "INGRESS" |
| 479 | + priority = 1000 |
| 480 | + source_ranges = ["34.71.242.81", "34.72.28.29", "34.67.6.157", "34.67.234.134", "34.72.239.218"] #Datastream IPs |
| 481 | +
|
| 482 | +} |
| 483 | +
|
| 484 | +resource "google_datastream_connection_profile" "ssh_connectivity_profile" { |
| 485 | + display_name = "Source connection profile" |
| 486 | + location = "us-central1" |
| 487 | + connection_profile_id = "tf-test-pg-profile%{random_suffix}" |
| 488 | +
|
| 489 | + postgresql_profile { |
| 490 | + hostname = google_sql_database_instance.instance.public_ip_address |
| 491 | + username = google_sql_user.user.name |
| 492 | + password = google_sql_user.user.password |
| 493 | + database = google_sql_database.db.name |
| 494 | + port = 5432 |
| 495 | + } |
| 496 | +
|
| 497 | + forward_ssh_connectivity { |
| 498 | + hostname = google_compute_instance.default.network_interface.0.access_config.0.nat_ip |
| 499 | + username = google_sql_user.user.name |
| 500 | + port = 22 |
| 501 | + private_key = <<EOT |
| 502 | +%{private_key} |
| 503 | +EOT |
| 504 | + } |
| 505 | +
|
| 506 | + depends_on = [time_sleep.ssh_host_wait] |
| 507 | + timeouts { |
| 508 | + create = "10m" |
| 509 | + } |
| 510 | + %{lifecycle_block} |
| 511 | +} |
| 512 | +`, context) |
| 513 | +} |
0 commit comments