-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SSH for Postgres Source #5742
SSH for Postgres Source #5742
Conversation
/test connector=connectors/source-postgres
|
/test connector=connectors/source-postgres
|
/test connector=connectors/source-postgres
|
/test connector=connectors/source-postgres
|
@@ -105,7 +106,10 @@ protected String getImageName() { | |||
|
|||
@Override | |||
protected ConnectorSpecification getSpec() throws Exception { | |||
return Jsons.deserialize(MoreResources.readResource("spec.json"), ConnectorSpecification.class); | |||
final ConnectorSpecification originalSpec = Jsons.deserialize(MoreResources.readResource("spec.json"), ConnectorSpecification.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this use a function to match the actual getspec?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added it in ssh helpers
.../src/test/java/io/airbyte/integrations/source/postgres/PostgresJdbcSourceAcceptanceTest.java
Show resolved
Hide resolved
...rbyte/integrations/io/airbyte/integration_tests/sources/CdcPostgresSourceAcceptanceTest.java
Outdated
Show resolved
Hide resolved
@@ -5,6 +5,12 @@ plugins { | |||
|
|||
dependencies { | |||
implementation 'commons-cli:commons-cli:1.4' | |||
implementation group: 'org.apache.sshd', name: 'sshd-mina', version: '2.7.0' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: formatting doesn't match the 'commons-cli:commons-cli:1.4'
style we're using elsewhere.
...rs/source-postgres/src/main/java/io/airbyte/integrations/source/postgres/PostgresSource.java
Outdated
Show resolved
Hide resolved
Preconditions.checkNotNull(tunnelSshPort); | ||
Preconditions.checkNotNull(user); | ||
Preconditions.checkArgument(sshKey != null || password != null, | ||
"SSH Tunnel was requested to be opened while it was already open. This is a coding error."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this error message correct? i'm not sure how it relates to the condition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nope. fixed.
this.tunnelDatabasePort = tunnelDatabasePort; | ||
|
||
this.sshclient = createClient(); | ||
this.tunnelSession = openTunnel(sshclient); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are we opening a tunnel in the constructor of this object? shouldn't this either be opened explicitly or be re-entrant/a singleton?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why? the original version was a mix between a factory and this. so i just picked one of the patterns. what does singleton or reentrant get us here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, I mixed two concerns in my initial comment.
- The main unexpected behavior I'm seeing here is that we instantiate a tunnel upon creating an object. It just seemed unintuitive. I guess this is fine since it's meant to be used in a try-with-resources?
- I remember there was a case where we got into trouble for trying to open the tunnel twice (because read calls check or something) hence the re-entrant suggestion, so we don't create two tunnels.
"multiline": true, | ||
"order": 4 | ||
}, | ||
"tunnel_db_remote_host": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO this should be the current hostname field, no need to add an extra host field.
Transparently we should replace the host field with localhost
and use this in the SSH tunnel config instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah. good point. let me see what i need to do to make that work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sherifnada - i followed the path here. it complicates the code a fair amount, but it does provide a better use experience. i think it is the right thing to do, but would love to get your eyes on it before I go forward. You can either look at this PR as it is now or if you want to see exactly what had to change see this commit: d55049d.
The thing that is a bit complicated is that you need to add logic that:
- knows what fields in the config are the host and port
- replaces those with localhost and the port that we use for the tunnel
- make sure the source actually uses the new config
Because this is tricky, I went ahead and did the same SshSource decorator that I did for the destination. I think that at least contains all of the complexity in one spot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice job! I think you placed it in a good place
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Marked as approve so I'm non-blocking. The only important change is to modify that toString() method so creds don't end up in a log file. The rest is just style.
", tunnelSshPort='" + tunnelSshPort + '\'' + | ||
", user='" + user + '\'' + | ||
", sshkey='" + sshkey + '\'' + | ||
", password='" + password + '\'' + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The secrets (key, pass) should not be included in the toString method, as it can leak secrets to logs.
|
||
if (check.getStatus().equals(AirbyteConnectionStatus.Status.FAILED)) { | ||
throw new RuntimeException("Unable establish a connection: " + check.getMessage()); | ||
final SshTunnel tunnel = SshTunnel.getInstance(config); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're getting a tunnel instance here but I don't see a call to open the tunnel. Is that a coding mistake, or is the call happening farther in?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i changed the structure of the class so that when the tunnel class is instantiated it immediately creates the actual ssh tunnel.
@sherifnada do you have any opinions on the spec. are these the clearest names? I did a rename within the constructor of One additional thing, I'm considering is removing the name "database" from any of the fields. After all, all of the SSH machinery can be used for any resource that we want to access via an ssh tunnel. The only remenents of it being specific to a db at this point is that some fields have the word database in them. so something like:
wdyt? |
/test connector=connectors/source-postgres
|
/test connector=connectors/source-postgres
|
My only gripe here is that for the foreseeable future, we're only gonna be doing this for DBs. I think the actual variable name is better with your change, but the |
@sherifnada agreed. it is one of those things that is pretty painful to change that's why i was thinking about being forward thinking. i'll do as you suggest, i will change the names in the spec to say resource, but the titles will say db. thanks! once that's done, i'll publish and merge. |
/test connector=connectors/source-postgres
|
/test connector=connectors/source-postgres
|
37f685d
to
437fb14
Compare
/test connector=connectors/source-postgres
|
/publish connector=connectors/source-postgres
|
What
How
PostgresSource
directly. This make it relatively straightforward to inject without worrying about touching other jdbc dbs.Recommended reading order
PostgresSource.java
SshTunnel.python
AbstractSshPostgresSourceAcceptanceTest.java
SshPasswordPostgresSourceAcceptanceTest.java
Pre-merge Checklist