Skip to content

Commit

Permalink
eclipse-ditto#985 reject ssh tunneling for kafka connections
Browse files Browse the repository at this point in the history
Signed-off-by: Dominik Guggemos <dominik.guggemos@bosch.io>
  • Loading branch information
dguggemos committed Mar 26, 2021
1 parent 4cb49fb commit 2b49516
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@
"$id": "/properties/sshTunnel/properties/validateHost",
"type": "boolean",
"title": "Whether the SSH host is verified.",
"description": "This flag controls whether Ditto verifies the SSH host used for tunneling by chacking the public key provided by the host against the given public key fingerprints."
"description": "This flag controls whether Ditto verifies the SSH host used for tunneling by checking the public key provided by the host against the given public key fingerprints."
},
"knownHosts": {
"$id": "/properties/sshTunnel/properties/knownHosts",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,16 @@ void validate(final Connection connection, final DittoHeaders dittoHeaders, fina
final HostValidator hostValidator = new HostValidator(connectivityConfig, loggingAdapter);
hostValidator.validateHostname(connection.getHostname(), dittoHeaders);

// tunneling not supported for kafka
if (ConnectionType.KAFKA == connection.getConnectionType() && connection.getSshTunnel().isPresent()) {
throw ConnectionConfigurationInvalidException
.newBuilder("SSH tunneling not supported.")
.description(
"SSH tunneling is not supported for the connection type <" + ConnectionType.KAFKA + ">.")
.dittoHeaders(dittoHeaders)
.build();
}

// validate ssh tunnel
connection.getSshTunnel().ifPresent(tunnel -> SshTunnelValidator.getInstance(dittoHeaders).validate(tunnel));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
/**
* Validates the ssh tunnel configuration of a connection.
*/
public final class SshTunnelValidator {
final class SshTunnelValidator {

private static final String SSH_SCHEME = "ssh";
private final DittoHeaders dittoHeaders;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,14 @@ public static final class Mapping {
"}";
}

public static final class Tunnel {

public static final SshTunnel VALID_SSH_TUNNEL =
ConnectivityModelFactory.newSshTunnel(true, UserPasswordCredentials.newInstance("username", "password"),
true, List.of("MD5:11:22:33:44:55"), "ssh://host:2222");

}

public static final String MODIFY_THING_WITH_ACK =
"{\"topic\":\"ditto/thing/things/twin/commands/modify\"," +
"\"headers\":{\"content-type\":\"application/vnd.eclipse.ditto+json\"," +
Expand Down Expand Up @@ -805,7 +813,11 @@ public static Connection createConnection() {
}

public static Connection createConnection(final String uri) {
return ConnectivityModelFactory.newConnectionBuilder(createRandomConnectionId(), TYPE,
return createConnection(uri, TYPE);
}

public static Connection createConnection(final String uri, final ConnectionType connectionType) {
return ConnectivityModelFactory.newConnectionBuilder(createRandomConnectionId(), connectionType,
ConnectivityStatus.OPEN, uri)
.sources(Sources.SOURCES_WITH_AUTH_CONTEXT)
.targets(Targets.TARGETS)
Expand Down Expand Up @@ -837,17 +849,33 @@ public static Connection createConnectionWithTunnel(final boolean enabled) {
}

public static Connection createConnection(final ConnectionId connectionId) {
return createConnection(connectionId, Sources.SOURCES_WITH_AUTH_CONTEXT);
return createConnection(connectionId, TYPE, Sources.SOURCES_WITH_AUTH_CONTEXT);
}

public static Connection createConnection(final ConnectionId connectionId, final ConnectionType connectionType) {
return createConnection(connectionId, connectionType, Sources.SOURCES_WITH_AUTH_CONTEXT);
}

public static Connection createConnection(final ConnectionId connectionId, final List<Source> sources) {
return createConnection(connectionId, STATUS, sources);
return createConnection(connectionId, TYPE, STATUS, sources);
}

public static Connection createConnection(final ConnectionId connectionId, final ConnectionType connectionType,
final List<Source> sources) {
return createConnection(connectionId, connectionType, STATUS, sources);
}

public static Connection createConnection(final ConnectionId connectionId, final ConnectivityStatus status,
final List<Source> sources) {
return createConnection(connectionId, TYPE, status, sources);
}

return ConnectivityModelFactory.newConnectionBuilder(connectionId, TYPE, status, getUriOfNewMockServer())
public static Connection createConnection(final ConnectionId connectionId, final ConnectionType connectionType,
final ConnectivityStatus status,
final List<Source> sources) {

return ConnectivityModelFactory.newConnectionBuilder(connectionId, connectionType, status,
getUriOfNewMockServer())
.sources(sources)
.targets(Targets.TARGETS)
.lifecycle(ConnectionLifecycle.ACTIVE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,20 @@ public void acceptClientCertificate() {
underTest.validate(connection, DittoHeaders.empty(), actorSystem);
}

@Test
public void rejectKafkaConnectionWithTunnel() {
final Connection connection = TestConstants.createConnection(CONNECTION_ID, ConnectionType.KAFKA)
.toBuilder()
.uri("amqps://8.8.4.4:443")
.sshTunnel(TestConstants.Tunnel.VALID_SSH_TUNNEL)
.build();

final ConnectionValidator underTest = getConnectionValidator();
assertThatExceptionOfType(ConnectionConfigurationInvalidException.class)
.isThrownBy(() -> underTest.validate(connection, DittoHeaders.empty(), actorSystem))
.withMessage("SSH tunneling not supported.");
}

@Test
public void testInvalidHosts() {
final ConnectionValidator underTest = getConnectionValidator();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
package org.eclipse.ditto.services.connectivity.messaging.validation;

import static org.assertj.core.api.Assertions.assertThatExceptionOfType;

import java.util.List;
import static org.eclipse.ditto.services.connectivity.messaging.TestConstants.Tunnel.VALID_SSH_TUNNEL;

import org.eclipse.ditto.model.base.headers.DittoHeaders;
import org.eclipse.ditto.model.connectivity.ConnectionConfigurationInvalidException;
Expand All @@ -30,9 +29,7 @@
*/
public class SshTunnelValidatorTest {

private static final SshTunnel VALID_SSH_TUNNEL =
ConnectivityModelFactory.newSshTunnel(true, UserPasswordCredentials.newInstance("username", "password"),
true, List.of("MD5:11:22:33:44:55"), "ssh://host:2222");

private static final DittoHeaders DITTO_HEADERS = DittoHeaders.newBuilder().randomCorrelationId().build();
private static final SshTunnelValidator VALIDATOR = SshTunnelValidator.getInstance(DITTO_HEADERS);

Expand Down

0 comments on commit 2b49516

Please sign in to comment.