Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 2 additions & 13 deletions cs/src/Connections/TunnelRelayTunnelHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,10 @@ protected override async Task<ITunnelConnector> CreateTunnelConnectorAsync(Cance
Requires.Argument(this.accessToken != null, nameof(Tunnel), $"There is no access token for {TunnelAccessScope} scope on the tunnel.");

var hostPublicKey = HostPrivateKey.GetPublicKeyBytes(HostPrivateKey.KeyAlgorithmName).ToBase64();
var tunnelHasSshPort = Tunnel.Ports != null &&
Tunnel.Ports.Any((p) => p.Protocol == TunnelProtocol.Ssh);
var endpointSignature =
$"{Tunnel.TunnelId}.{Tunnel.ClusterId}:" +
$"{Tunnel.Name}.{Tunnel.Domain}:" +
$"{tunnelHasSshPort}:{this.hostId}:{hostPublicKey}";
$"{this.hostId}:{hostPublicKey}";

if (!string.Equals(endpointSignature, EndpointSignature, StringComparison.OrdinalIgnoreCase) ||
RelayUri == null)
Expand All @@ -147,19 +145,10 @@ protected override async Task<ITunnelConnector> CreateTunnelConnectorAsync(Cance
HostPublicKeys = new[] { hostPublicKey },
};

List<KeyValuePair<string, string>>? additionalQueryParams = null;
if (tunnelHasSshPort)
{
additionalQueryParams = new () {new KeyValuePair<string, string>("includeSshGatewayPublicKey", "true")};
}

endpoint = (TunnelRelayTunnelEndpoint)await ManagementClient!.UpdateTunnelEndpointAsync(
Tunnel,
endpoint,
options: new TunnelRequestOptions()
{
AdditionalQueryParameters = additionalQueryParams,
},
options: null,
cancellation);
Comment thread
DavidObando marked this conversation as resolved.

EndpointSignature = endpointSignature;
Expand Down
4 changes: 2 additions & 2 deletions cs/src/Contracts/TunnelPort.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public TunnelPort()
/// <para/>
/// Selection of a default port for a connection also depends on matching the connection to the
/// port <see cref="Protocol" />, so it is possible to configure separate defaults for distinct
/// protocols like <see cref="TunnelProtocol.Http" /> and <see cref="TunnelProtocol.Ssh" />.
/// protocols like <see cref="TunnelProtocol.Http" /> and <see cref="TunnelProtocol.Tcp" />.
/// </remarks>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public bool IsDefault { get; set; }
Expand Down Expand Up @@ -134,7 +134,7 @@ public TunnelPort()
/// Gets or sets the username for the ssh service user is trying to forward.
/// </summary>
/// <remarks>
/// Should be provided if the <see cref="TunnelProtocol"/> is Ssh.
/// This property is retained for compatibility with legacy SSH tunnel ports.
/// </remarks>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[StringLength(SshUserMaxLength)]
Expand Down
5 changes: 0 additions & 5 deletions cs/src/Contracts/TunnelProtocol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,6 @@ public static class TunnelProtocol
/// </summary>
public const string Udp = "udp";

/// <summary>
/// SSH protocol.
/// </summary>
public const string Ssh = "ssh";

/// <summary>
/// Remote desktop protocol.
/// </summary>
Expand Down
3 changes: 3 additions & 0 deletions cs/test/TunnelsSDK.Test/Mocks/MockTunnelManagementClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ public Task<TunnelEndpoint> UpdateTunnelEndpointAsync(
CancellationToken cancellation = default)
{
TunnelEndpointsUpdated++;
LastTunnelEndpointUpdateOptions = options;
tunnel.Endpoints ??= Array.Empty<TunnelEndpoint>();

for (int i = 0; i < tunnel.Endpoints.Length; i++)
Expand Down Expand Up @@ -153,6 +154,8 @@ public Task<TunnelEndpoint> UpdateTunnelEndpointAsync(

public int TunnelEndpointsUpdated { get; private set; }

public TunnelRequestOptions LastTunnelEndpointUpdateOptions { get; private set; }

public Task<bool> DeleteTunnelEndpointsAsync(
Tunnel tunnel,
string Id,
Expand Down
29 changes: 29 additions & 0 deletions cs/test/TunnelsSDK.Test/TunnelHostAndClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,35 @@ public async Task ConnectRelayHost()
await clientSshSession.ConnectAsync(clientRelayStream, TestContext.Current.CancellationToken);
}

[Fact]
public async Task ConnectRelayHostWithLegacySshPortDoesNotRequestSshGatewayKey()
{
var managementClient = new MockTunnelManagementClient
{
HostRelayUri = MockHostRelayUri,
};
var relayHost = new TunnelRelayTunnelHost(managementClient, TestTS);
var tunnel = CreateRelayTunnel();
tunnel.Ports =
[
new TunnelPort
{
PortNumber = 22,
Protocol = "ssh",
},
];

using var serverSshSession = await ConnectRelayHostAsync(
relayHost,
tunnel,
cancellation: TestContext.Current.CancellationToken);

Assert.Equal(1, managementClient.TunnelEndpointsUpdated);
Assert.Null(managementClient.LastTunnelEndpointUpdateOptions);

await relayHost.DisposeAsync();
}

[Fact]
public async Task ConnectRelayHostAfterDisconnect()
{
Expand Down
4 changes: 2 additions & 2 deletions go/tunnels/tunnel_port.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ type TunnelPort struct {
//
// Selection of a default port for a connection also depends on matching the connection
// to the port `TunnelPort.Protocol`, so it is possible to configure separate defaults
// for distinct protocols like `TunnelProtocol.Http` and `TunnelProtocol.Ssh`.
// for distinct protocols like `TunnelProtocol.Http` and `TunnelProtocol.Tcp`.
IsDefault bool `json:"isDefault,omitempty"`

// Gets or sets a dictionary mapping from scopes to tunnel access tokens.
Expand All @@ -61,7 +61,7 @@ type TunnelPort struct {

// Gets or sets the username for the ssh service user is trying to forward.
//
// Should be provided if the `TunnelProtocol` is Ssh.
// This property is retained for compatibility with legacy SSH tunnel ports.
SshUser string `json:"sshUser,omitempty"`

// Gets or sets web forwarding URIs. If set, it's a list of absolute URIs where the port
Expand Down
3 changes: 0 additions & 3 deletions go/tunnels/tunnel_protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ const (
// Unknown UDP protocol.
TunnelProtocolUdp TunnelProtocol = "udp"

// SSH protocol.
TunnelProtocolSsh TunnelProtocol = "ssh"

// Remote desktop protocol.
TunnelProtocolRdp TunnelProtocol = "rdp"

Expand Down
2 changes: 1 addition & 1 deletion go/tunnels/tunnels.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/rodaine/table"
)

const PackageVersion = "0.2.0"
const PackageVersion = "0.2.1"

func (tunnel *Tunnel) requestObject() (*Tunnel, error) {
convertedTunnel := &Tunnel{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public class TunnelPort {
* Selection of a default port for a connection also depends on matching the
* connection to the port {@link TunnelPort#protocol}, so it is possible to configure
* separate defaults for distinct protocols like {@link TunnelProtocol#http} and
* {@link TunnelProtocol#ssh}.
* {@link TunnelProtocol#tcp}.
*/
@Expose
public boolean isDefault;
Expand Down Expand Up @@ -105,7 +105,7 @@ public class TunnelPort {
/**
* Gets or sets the username for the ssh service user is trying to forward.
*
* Should be provided if the {@link TunnelProtocol} is Ssh.
* This property is retained for compatibility with legacy SSH tunnel ports.
*/
@Expose
public String sshUser;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@ public class TunnelProtocol {
*/
public static final String udp = "udp";

/**
* SSH protocol.
*/
public static final String ssh = "ssh";

/**
* Remote desktop protocol.
*/
Expand Down
4 changes: 2 additions & 2 deletions rs/src/contracts/tunnel_port.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub struct TunnelPort {
// Selection of a default port for a connection also depends on matching the
// connection to the port `TunnelPort.Protocol`, so it is possible to configure
// separate defaults for distinct protocols like `TunnelProtocol.Http` and
// `TunnelProtocol.Ssh`.
// `TunnelProtocol.Tcp`.
#[serde(default)]
pub is_default: bool,

Expand All @@ -79,7 +79,7 @@ pub struct TunnelPort {

// Gets or sets the username for the ssh service user is trying to forward.
//
// Should be provided if the `TunnelProtocol` is Ssh.
// This property is retained for compatibility with legacy SSH tunnel ports.
#[serde(skip_serializing_if = "Option::is_none")]
pub ssh_user: Option<String>,

Expand Down
3 changes: 0 additions & 3 deletions rs/src/contracts/tunnel_protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ pub const TUNNEL_PROTOCOL_TCP: &str = r#"tcp"#;
// Unknown UDP protocol.
pub const TUNNEL_PROTOCOL_UDP: &str = r#"udp"#;

// SSH protocol.
pub const TUNNEL_PROTOCOL_SSH: &str = r#"ssh"#;

// Remote desktop protocol.
pub const TUNNEL_PROTOCOL_RDP: &str = r#"rdp"#;

Expand Down
13 changes: 2 additions & 11 deletions ts/src/connections/tunnelRelayTunnelHost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import {
TunnelConnectionMode,
TunnelProtocol,
TunnelRelayTunnelEndpoint,
TunnelPort,
Tunnel,
Expand Down Expand Up @@ -284,11 +283,10 @@ export class TunnelRelayTunnelHost extends TunnelConnectionSession implements Tu
this.hostPublicKeys = [buffer.toString('base64')];
}

const tunnelHasSshPort = this.tunnel?.ports != null && this.tunnel.ports.find((v) => v.protocol === TunnelProtocol.Ssh);
const endpointSignature =
`${this.tunnel?.tunnelId}.${this.tunnel?.clusterId}:` +
`${this.tunnel?.name}.${this.tunnel?.domain}:` +
`${tunnelHasSshPort}:${this.hostId}:${this.hostPublicKeys}`;
`${this.hostId}:${this.hostPublicKeys}`;

if (!this.relayUri || this.endpointSignature !== endpointSignature) {
if (!this.tunnel) {
Expand All @@ -302,14 +300,7 @@ export class TunnelRelayTunnelHost extends TunnelConnectionSession implements Tu
connectionMode: TunnelConnectionMode.TunnelRelay,
};

let additionalQueryParameters = undefined;
if (tunnelHasSshPort) {
additionalQueryParameters = { includeSshGatewayPublicKey: 'true' };
}

endpoint = await this.managementClient!.updateTunnelEndpoint(this.tunnel, endpoint, {
additionalQueryParameters: additionalQueryParameters,
});
endpoint = await this.managementClient!.updateTunnelEndpoint(this.tunnel, endpoint);
Comment thread
DavidObando marked this conversation as resolved.

this.relayUri = endpoint.hostRelayUri!;
this.endpointSignature = endpointSignature;
Expand Down
4 changes: 2 additions & 2 deletions ts/src/contracts/tunnelPort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export interface TunnelPort {
* Selection of a default port for a connection also depends on matching the
* connection to the port {@link TunnelPort.protocol}, so it is possible to configure
* separate defaults for distinct protocols like {@link TunnelProtocol.http} and
* {@link TunnelProtocol.ssh}.
* {@link TunnelProtocol.tcp}.
*/
isDefault?: boolean;

Expand Down Expand Up @@ -93,7 +93,7 @@ export interface TunnelPort {
/**
* Gets or sets the username for the ssh service user is trying to forward.
*
* Should be provided if the {@link TunnelProtocol} is Ssh.
* This property is retained for compatibility with legacy SSH tunnel ports.
*/
sshUser?: string;

Expand Down
5 changes: 0 additions & 5 deletions ts/src/contracts/tunnelProtocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@ export enum TunnelProtocol {
*/
Udp = 'udp',

/**
* SSH protocol.
*/
Ssh = 'ssh',

/**
* Remote desktop protocol.
*/
Expand Down
2 changes: 2 additions & 0 deletions ts/test/tunnels-test/mocks/mockTunnelManagementClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,15 @@ export class MockTunnelManagementClient implements TunnelManagementClient {
}

public tunnelEndpointsUpdated: number = 0;
public lastTunnelEndpointUpdateOptions?: TunnelRequestOptions;

updateTunnelEndpoint(
tunnel: Tunnel,
endpoint: TunnelEndpoint,
options?: TunnelRequestOptions,
): Promise<TunnelEndpoint> {
this.tunnelEndpointsUpdated++;
this.lastTunnelEndpointUpdateOptions = options;
if (!tunnel.endpoints) {
tunnel.endpoints = [];
}
Expand Down
16 changes: 16 additions & 0 deletions ts/test/tunnels-test/tunnelHostAndClientTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,22 @@ export class TunnelHostAndClientTests {
assert.strictEqual(relayHost.connectionStatus, ConnectionStatus.Disconnected);
}

@test
public async connectRelayHostWithLegacySshPortDoesNotRequestSshGatewayKey() {
const managementClient = new MockTunnelManagementClient();
managementClient.hostRelayUri = this.mockHostRelayUri;
const relayHost = new TunnelRelayTunnelHost(managementClient);
const tunnel = this.createRelayTunnel();
tunnel.ports = [{ portNumber: 22, protocol: 'ssh' }];

await this.connectRelayHost({ relayHost, tunnel });

assert.equal(1, managementClient.tunnelEndpointsUpdated);
assert.strictEqual(managementClient.lastTunnelEndpointUpdateOptions, undefined);

await relayHost.dispose();
}

@test
public async connectRelayHostAfterDisconnect() {
const managementClient = new MockTunnelManagementClient();
Expand Down
Loading