|
5 | 5 | package io.airbyte.integrations.source.postgres;
|
6 | 6 |
|
7 | 7 | import static org.junit.jupiter.api.Assertions.assertEquals;
|
| 8 | +import static org.junit.jupiter.api.Assertions.assertTrue; |
8 | 9 |
|
9 | 10 | import com.fasterxml.jackson.databind.JsonNode;
|
| 11 | +import com.fasterxml.jackson.databind.node.ObjectNode; |
10 | 12 | import com.google.common.collect.ImmutableMap;
|
| 13 | +import io.airbyte.commons.json.Jsons; |
11 | 14 | import io.airbyte.db.jdbc.JdbcUtils;
|
12 | 15 | import io.airbyte.integrations.base.ssh.SshBastionContainer;
|
13 | 16 | import io.airbyte.integrations.base.ssh.SshTunnel;
|
|
18 | 21 | import org.junit.jupiter.api.Test;
|
19 | 22 | import org.testcontainers.containers.Network;
|
20 | 23 | import org.testcontainers.containers.PostgreSQLContainer;
|
| 24 | +import org.testcontainers.utility.DockerImageName; |
21 | 25 |
|
22 | 26 | public class PostgresSourceStrictEncryptTest {
|
23 | 27 |
|
@@ -76,4 +80,67 @@ private ImmutableMap.Builder<Object, Object> getDatabaseConfigBuilderWithSSLMode
|
76 | 80 | .put(JdbcUtils.SSL_MODE_KEY, Map.of(JdbcUtils.MODE_KEY, sslMode));
|
77 | 81 | }
|
78 | 82 |
|
| 83 | + private JsonNode getMockedSSLConfig(String sslMode) { |
| 84 | + return Jsons.jsonNode(ImmutableMap.builder() |
| 85 | + .put(JdbcUtils.HOST_KEY, "test_host") |
| 86 | + .put(JdbcUtils.PORT_KEY, 777) |
| 87 | + .put(JdbcUtils.DATABASE_KEY, "test_db") |
| 88 | + .put(JdbcUtils.USERNAME_KEY, "test_user") |
| 89 | + .put(JdbcUtils.PASSWORD_KEY, "test_password") |
| 90 | + .put(JdbcUtils.SSL_KEY, true) |
| 91 | + .put(JdbcUtils.SSL_MODE_KEY, Map.of(JdbcUtils.MODE_KEY, sslMode)) |
| 92 | + .build()); |
| 93 | + } |
| 94 | + |
| 95 | + @Test |
| 96 | + void testSslModesUnsecuredNoTunnel() throws Exception { |
| 97 | + for (String sslMode : List.of("disable", "allow", "prefer")) { |
| 98 | + final JsonNode config = getMockedSSLConfig(sslMode); |
| 99 | + ((ObjectNode) config).putIfAbsent("tunnel_method", Jsons.jsonNode(ImmutableMap.builder() |
| 100 | + .put("tunnel_method", "NO_TUNNEL") |
| 101 | + .build())); |
| 102 | + |
| 103 | + final AirbyteConnectionStatus actual = new PostgresSourceStrictEncrypt().check(config); |
| 104 | + assertEquals(AirbyteConnectionStatus.Status.FAILED, actual.getStatus()); |
| 105 | + assertTrue(actual.getMessage().contains("Unsecured connection not allowed")); |
| 106 | + } |
| 107 | + } |
| 108 | + |
| 109 | + @Test |
| 110 | + void testSslModeRequiredNoTunnel() throws Exception { |
| 111 | + |
| 112 | + try (PostgreSQLContainer<?> db = |
| 113 | + new PostgreSQLContainer<>(DockerImageName.parse("marcosmarxm/postgres-ssl:dev").asCompatibleSubstituteFor("postgres")) |
| 114 | + .withCommand("postgres -c ssl=on -c ssl_cert_file=/var/lib/postgresql/server.crt -c ssl_key_file=/var/lib/postgresql/server.key")) { |
| 115 | + db.start(); |
| 116 | + |
| 117 | + final ImmutableMap<Object, Object> configBuilderWithSslModeRequire = getDatabaseConfigBuilderWithSSLMode(db, "require").build(); |
| 118 | + final JsonNode config = Jsons.jsonNode(configBuilderWithSslModeRequire); |
| 119 | + ((ObjectNode) config).putIfAbsent("tunnel_method", Jsons.jsonNode(ImmutableMap.builder() |
| 120 | + .put("tunnel_method", "NO_TUNNEL") |
| 121 | + .build())); |
| 122 | + final AirbyteConnectionStatus connectionStatusForPreferredMode = new PostgresSourceStrictEncrypt().check(config); |
| 123 | + assertEquals(AirbyteConnectionStatus.Status.SUCCEEDED, connectionStatusForPreferredMode.getStatus()); |
| 124 | + } |
| 125 | + } |
| 126 | + |
| 127 | + @Test |
| 128 | + void testStrictSSLSecuredWithTunnel() throws Exception { |
| 129 | + try (PostgreSQLContainer<?> db = |
| 130 | + new PostgreSQLContainer<>(DockerImageName.parse("marcosmarxm/postgres-ssl:dev").asCompatibleSubstituteFor("postgres")) |
| 131 | + .withCommand("postgres -c ssl=on -c ssl_cert_file=/var/lib/postgresql/server.crt -c ssl_key_file=/var/lib/postgresql/server.key") |
| 132 | + .withNetwork(network)) { |
| 133 | + |
| 134 | + bastion.initAndStartBastion(network); |
| 135 | + db.start(); |
| 136 | + |
| 137 | + final ImmutableMap.Builder<Object, Object> builderWithSSLModePrefer = getDatabaseConfigBuilderWithSSLMode(db, "require"); |
| 138 | + final JsonNode configWithSslAndSsh = bastion.getTunnelConfig(SshTunnel.TunnelMethod.SSH_PASSWORD_AUTH, builderWithSSLModePrefer); |
| 139 | + final AirbyteConnectionStatus connectionStatusForPreferredMode = new PostgresSourceStrictEncrypt().check(configWithSslAndSsh); |
| 140 | + assertEquals(AirbyteConnectionStatus.Status.SUCCEEDED, connectionStatusForPreferredMode.getStatus()); |
| 141 | + } finally { |
| 142 | + bastion.stopAndClose(); |
| 143 | + } |
| 144 | + } |
| 145 | + |
79 | 146 | }
|
0 commit comments