Skip to content

Commit 04d4163

Browse files
andriikorotkovoctavia-squidington-iii
authored andcommitted
🎉 Source MySql: Added SSL certificates to MySql Source (#15044)
* updated mysql source specification and added field for root and clients SSL certificates * added SSL mode for mysql source * fixed code style * updated run process timeout * updated method for create keystore and updated tests * updated normalization version for postgres destination * updated normalization version for postgres destination * added tests for connection with certificates * updated tests for connection with full certificates and added tests for CA certificate * updated tests * updated source-mysql-strict-encrypt and updated versions * updated code style * updated doc * updated specs * fixed minor remarks * fixed minor remarks * updated tests * fixed remarks and updated specification * fixed mysql sources connectors version * added CDC + SSL Certificates tests * added property for CDC and added tests for test SSL with CDC together * fixed MySqlStrictEncryptJdbcSourceAcceptanceTest for work with datetime format * added property for CDC and added tests for test SSL with CDC together * auto-bump connector version [ci skip] Co-authored-by: Octavia Squidington III <[email protected]>
1 parent c76e7d0 commit 04d4163

File tree

24 files changed

+1319
-25
lines changed

24 files changed

+1319
-25
lines changed

airbyte-config/init/src/main/resources/seed/source_definitions.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@
647647
- name: MySQL
648648
sourceDefinitionId: 435bb9a5-7887-4809-aa58-28c27df0d7ad
649649
dockerRepository: airbyte/source-mysql
650-
dockerImageTag: 0.6.2
650+
dockerImageTag: 0.6.3
651651
documentationUrl: https://docs.airbyte.io/integrations/sources/mysql
652652
icon: mysql.svg
653653
sourceType: database

airbyte-config/init/src/main/resources/seed/source_specs.yaml

Lines changed: 131 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5977,7 +5977,7 @@
59775977
supportsNormalization: false
59785978
supportsDBT: false
59795979
supported_destination_sync_modes: []
5980-
- dockerImage: "airbyte/source-mysql:0.6.2"
5980+
- dockerImage: "airbyte/source-mysql:0.6.3"
59815981
spec:
59825982
documentationUrl: "https://docs.airbyte.io/integrations/sources/mysql"
59835983
connectionSpecification:
@@ -6035,6 +6035,135 @@
60356035
type: "boolean"
60366036
default: true
60376037
order: 6
6038+
ssl_mode:
6039+
title: "SSL modes"
6040+
description: "SSL connection modes. <li><b>preferred</b> - Automatically\
6041+
\ attempt SSL connection. If the MySQL server does not support SSL, continue\
6042+
\ with a regular connection.</li><li><b>required</b> - Always connect\
6043+
\ with SSL. If the MySQL server doesn’t support SSL, the connection will\
6044+
\ not be established. Certificate Authority (CA) and Hostname are not\
6045+
\ verified.</li><li><b>verify-ca</b> - Always connect with SSL. Verifies\
6046+
\ CA, but allows connection even if Hostname does not match.</li><li><b>Verify\
6047+
\ Identity</b> - Always connect with SSL. Verify both CA and Hostname.</li></ul>Read\
6048+
\ more <a href=\"https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-using-ssl.html\"\
6049+
> in the docs</a>."
6050+
type: "object"
6051+
order: 7
6052+
oneOf:
6053+
- title: "preferred"
6054+
description: "Preferred SSL mode."
6055+
required:
6056+
- "mode"
6057+
properties:
6058+
mode:
6059+
type: "string"
6060+
const: "preferred"
6061+
enum:
6062+
- "preferred"
6063+
default: "preferred"
6064+
order: 0
6065+
- title: "required"
6066+
description: "Require SSL mode."
6067+
required:
6068+
- "mode"
6069+
properties:
6070+
mode:
6071+
type: "string"
6072+
const: "required"
6073+
enum:
6074+
- "required"
6075+
default: "required"
6076+
order: 0
6077+
- title: "Verify CA"
6078+
description: "Verify CA SSL mode."
6079+
required:
6080+
- "mode"
6081+
- "ca_certificate"
6082+
properties:
6083+
mode:
6084+
type: "string"
6085+
const: "verify_ca"
6086+
enum:
6087+
- "verify_ca"
6088+
default: "verify_ca"
6089+
order: 0
6090+
ca_certificate:
6091+
type: "string"
6092+
title: "CA certificate"
6093+
description: "CA certificate"
6094+
airbyte_secret: true
6095+
multiline: true
6096+
order: 1
6097+
client_certificate:
6098+
type: "string"
6099+
title: "Client certificate"
6100+
description: "Client certificate (this is not a required field, but\
6101+
\ if you want to use it, you will need to add the <b>Client key</b>\
6102+
\ as well)"
6103+
airbyte_secret: true
6104+
multiline: true
6105+
order: 2
6106+
client_key:
6107+
type: "string"
6108+
title: "Client key"
6109+
description: "Client key (this is not a required field, but if you\
6110+
\ want to use it, you will need to add the <b>Client certificate</b>\
6111+
\ as well)"
6112+
airbyte_secret: true
6113+
multiline: true
6114+
order: 3
6115+
client_key_password:
6116+
type: "string"
6117+
title: "Client key password (Optional)"
6118+
description: "Password for keystorage. This field is optional. If\
6119+
\ you do not add it - the password will be generated automatically."
6120+
airbyte_secret: true
6121+
order: 4
6122+
- title: "Verify Identity"
6123+
description: "Verify-full SSL mode."
6124+
required:
6125+
- "mode"
6126+
- "ca_certificate"
6127+
properties:
6128+
mode:
6129+
type: "string"
6130+
const: "verify_identity"
6131+
enum:
6132+
- "verify_identity"
6133+
default: "verify_identity"
6134+
order: 0
6135+
ca_certificate:
6136+
type: "string"
6137+
title: "CA certificate"
6138+
description: "CA certificate"
6139+
airbyte_secret: true
6140+
multiline: true
6141+
order: 1
6142+
client_certificate:
6143+
type: "string"
6144+
title: "Client certificate"
6145+
description: "Client certificate (this is not a required field, but\
6146+
\ if you want to use it, you will need to add the <b>Client key</b>\
6147+
\ as well)"
6148+
airbyte_secret: true
6149+
multiline: true
6150+
order: 2
6151+
client_key:
6152+
type: "string"
6153+
title: "Client key"
6154+
description: "Client key (this is not a required field, but if you\
6155+
\ want to use it, you will need to add the <b>Client certificate</b>\
6156+
\ as well)"
6157+
airbyte_secret: true
6158+
multiline: true
6159+
order: 3
6160+
client_key_password:
6161+
type: "string"
6162+
title: "Client key password (Optional)"
6163+
description: "Password for keystorage. This field is optional. If\
6164+
\ you do not add it - the password will be generated automatically."
6165+
airbyte_secret: true
6166+
order: 4
60386167
replication_method:
60396168
type: "string"
60406169
title: "Replication Method"
@@ -6043,7 +6172,7 @@
60436172
\ but will not be able to represent deletions incrementally. CDC uses\
60446173
\ the Binlog to detect inserts, updates, and deletes. This needs to be\
60456174
\ configured on the source database itself."
6046-
order: 7
6175+
order: 8
60476176
default: "STANDARD"
60486177
enum:
60496178
- "STANDARD"

airbyte-db/db-lib/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ dependencies {
1515

1616
// Mark as compile only to avoid leaking transitively to connectors
1717
compileOnly libs.platform.testcontainers.postgresql
18+
compileOnly libs.connectors.testcontainers.mysql
1819

1920
// These are required because gradle might be using lower version of Jna from other
2021
// library transitive dependency. Can be removed if we can figure out which library is the cause.
@@ -25,6 +26,7 @@ dependencies {
2526
testImplementation project(':airbyte-test-utils')
2627
testImplementation 'org.apache.commons:commons-lang3:3.11'
2728
testImplementation libs.platform.testcontainers.postgresql
29+
testImplementation libs.connectors.testcontainers.mysql
2830

2931
// Big Query
3032
implementation('com.google.cloud:google-cloud-bigquery:1.133.1')
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright (c) 2022 Airbyte, Inc., all rights reserved.
3+
*/
4+
5+
package io.airbyte.db;
6+
7+
import com.google.common.annotations.VisibleForTesting;
8+
import java.io.IOException;
9+
import org.testcontainers.containers.MySQLContainer;
10+
11+
public class MySqlUtils {
12+
13+
@VisibleForTesting
14+
public static Certificate getCertificate(final MySQLContainer<?> container,
15+
final boolean useAllCertificates)
16+
throws IOException, InterruptedException {
17+
// add root and server certificates to config file
18+
container.execInContainer("sh", "-c", "sed -i '31 a ssl' /etc/my.cnf");
19+
container.execInContainer("sh", "-c", "sed -i '32 a ssl-ca=/var/lib/mysql/ca.pem' /etc/my.cnf");
20+
container.execInContainer("sh", "-c", "sed -i '33 a ssl-cert=/var/lib/mysql/server-cert.pem' /etc/my.cnf");
21+
container.execInContainer("sh", "-c", "sed -i '34 a ssl-key=/var/lib/mysql/server-key.pem' /etc/my.cnf");
22+
container.execInContainer("sh", "-c", "sed -i '35 a require_secure_transport=ON' /etc/my.cnf");
23+
// add client certificates to config file
24+
if (useAllCertificates) {
25+
container.execInContainer("sh", "-c", "sed -i '39 a [client]' /etc/mysql/my.cnf");
26+
container.execInContainer("sh", "-c", "sed -i '40 a ssl-ca=/var/lib/mysql/ca.pem' /etc/my.cnf");
27+
container.execInContainer("sh", "-c", "sed -i '41 a ssl-cert=/var/lib/mysql/client-cert.pem' /etc/my.cnf");
28+
container.execInContainer("sh", "-c", "sed -i '42 a ssl-key=/var/lib/mysql/client-key.pem' /etc/my.cnf");
29+
}
30+
// copy root certificate and client certificates
31+
var caCert = container.execInContainer("sh", "-c", "cat /var/lib/mysql/ca.pem").getStdout().trim();
32+
33+
if (useAllCertificates) {
34+
var clientKey = container.execInContainer("sh", "-c", "cat /var/lib/mysql/client-key.pem").getStdout().trim();
35+
var clientCert = container.execInContainer("sh", "-c", "cat /var/lib/mysql/client-cert.pem").getStdout().trim();
36+
return new Certificate(caCert, clientCert, clientKey);
37+
} else {
38+
return new Certificate(caCert);
39+
}
40+
}
41+
42+
public static class Certificate {
43+
44+
private final String caCertificate;
45+
private final String clientCertificate;
46+
private final String clientKey;
47+
48+
public Certificate(final String caCertificate) {
49+
this.caCertificate = caCertificate;
50+
this.clientCertificate = null;
51+
this.clientKey = null;
52+
}
53+
54+
public Certificate(final String caCertificate, final String clientCertificate, final String clientKey) {
55+
this.caCertificate = caCertificate;
56+
this.clientCertificate = clientCertificate;
57+
this.clientKey = clientKey;
58+
}
59+
60+
public String getCaCertificate() {
61+
return caCertificate;
62+
}
63+
64+
public String getClientCertificate() {
65+
return clientCertificate;
66+
}
67+
68+
public String getClientKey() {
69+
return clientKey;
70+
}
71+
72+
}
73+
74+
}

airbyte-db/db-lib/src/main/java/io/airbyte/db/jdbc/JdbcUtils.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ public class JdbcUtils {
3232
public static final String SSL_MODE_KEY = "ssl_mode";
3333
public static final String TLS_KEY = "tls";
3434
public static final String USERNAME_KEY = "username";
35+
public static final String MODE_KEY = "mode";
36+
public static final String AMPERSAND = "&";
3537
private static final JdbcSourceOperations defaultSourceOperations = new JdbcSourceOperations();
3638

3739
private static final JSONFormat defaultJSONFormat = new JSONFormat().recordFormat(JSONFormat.RecordFormat.OBJECT);

0 commit comments

Comments
 (0)