public async Task WhenClosingSessionBeforeChannel_ThenDoubleFreeIsPrevented( [LinuxInstance] ResourceTask <InstanceLocator> instanceLocatorTask) { var instanceLocator = await instanceLocatorTask; var endpoint = new IPEndPoint( await InstanceUtil.PublicIpAddressForInstanceAsync(await instanceLocatorTask), 22); using (var key = new RsaSshKey(new RSACng())) { await InstanceUtil.AddPublicKeyToMetadata( instanceLocator, "testuser", key).ConfigureAwait(true); var session = CreateSession(); var connection = session.Connect(endpoint); var authSession = connection.Authenticate( "testuser", key, UnexpectedAuthenticationCallback); var channel = authSession.OpenExecChannel( "whoami", LIBSSH2_CHANNEL_EXTENDED_DATA.NORMAL); session.Dispose(); // Free channel after session - note that this causes an assertion // when debugging. channel.Dispose(); } }
public async Task When2faRequiredAndPromptThrowsException_ThenAuthenticationFailsWithoutRetry( [LinuxInstance(InitializeScript = RequireSshPassword)] ResourceTask <InstanceLocator> instanceLocatorTask) { var endpoint = new IPEndPoint( await InstanceUtil.PublicIpAddressForInstanceAsync(await instanceLocatorTask), 22); using (var key = new RsaSshKey(new RSACng())) { await InstanceUtil.AddPublicKeyToMetadata( await instanceLocatorTask, "testuser", key); using (var session = CreateSession()) using (var connection = session.Connect(endpoint)) { var callbackCount = 0; Assert.Throws <OperationCanceledException>( () => connection.Authenticate( "testuser", key, (name, instruction, prompt, echo) => { callbackCount++; throw new OperationCanceledException(); })); Assert.AreEqual(1, callbackCount); } } }
public async Task WhenNonWhitelistedEnvironmentVariablePassed_ThenOpenShellChannelAsyncThrowsRequestDenied( [LinuxInstance] ResourceTask <InstanceLocator> instanceLocatorTask) { var endpoint = new IPEndPoint( await InstanceUtil.PublicIpAddressForInstanceAsync(await instanceLocatorTask), 22); using (var key = new RsaSshKey(new RSACng())) { await InstanceUtil.AddPublicKeyToMetadata( await instanceLocatorTask, "testuser", key).ConfigureAwait(true); using (var session = CreateSession()) using (var connection = session.Connect(endpoint)) using (var authSession = connection.Authenticate("testuser", key)) { SshAssert.ThrowsNativeExceptionWithError( session, LIBSSH2_ERROR.CHANNEL_REQUEST_DENIED, () => authSession.OpenShellChannel( LIBSSH2_CHANNEL_EXTENDED_DATA.MERGE, DefaultTerminal, 80, 24, new[] { new EnvironmentVariable("FOO", "foo", true), new EnvironmentVariable("BAR", "bar", true) })); } } }
public async Task WhenPublicKeyValidAndKnownFromMetadata_ThenAuthenticationSucceeds( [LinuxInstance] ResourceTask <InstanceLocator> instanceLocatorTask) { var endpoint = new IPEndPoint( await InstanceUtil.PublicIpAddressForInstanceAsync(await instanceLocatorTask), 22); using (var key = new RsaSshKey(new RSACng())) { await InstanceUtil.AddPublicKeyToMetadata( await instanceLocatorTask, "testuser", key); using (var session = CreateSession()) using (var connection = session.Connect(endpoint)) { var authSession = connection.Authenticate( "testuser", key, this.UnexpectedAuthenticationCallback); Assert.IsNotNull(authSession); } } }
public async Task WhenDisposingConnection_ThenWorkerIsStopped( [LinuxInstance] ResourceTask <InstanceLocator> instanceLocatorTask) { var endpoint = new IPEndPoint( await InstanceUtil.PublicIpAddressForInstanceAsync(await instanceLocatorTask), 22); using (var key = new RsaSshKey(new RSACng())) { await InstanceUtil.AddPublicKeyToMetadata( await instanceLocatorTask, "testuser", key); using (var connection = new SshShellConnection( "testuser", endpoint, key, SshShellConnection.DefaultTerminal, SshShellConnection.DefaultTerminalSize, CultureInfo.InvariantCulture, _ => { }, exception => { Assert.Fail("Unexpected error"); })) { await connection.ConnectAsync(); } } }
public async Task WhenProjectAndInstanceMetadataAllowed_ThenAuthorizeKeyAsyncPushesKeyToProjectMetadata() { var computeEngineAdapter = CreateComputeEngineAdapterMock( osLoginEnabledForProject: null, osLoginEnabledForInstance: null, osLogin2fa: false, legacySshKeyPresent: false, projectWideKeysBlockedForProject: false, projectWideKeysBlockedForInstance: false); var service = new AuthorizedKeyService( CreateAuthorizationAdapterMock().Object, computeEngineAdapter.Object, CreateResourceManagerAdapterMock(true).Object, CreateOsLoginServiceMock().Object); using (var key = RsaSshKey.NewEphemeralKey()) { var authorizedKey = await service.AuthorizeKeyAsync( SampleLocator, key, TimeSpan.FromMinutes(1), null, AuthorizeKeyMethods.All, CancellationToken.None); Assert.IsNotNull(authorizedKey); Assert.AreEqual(AuthorizeKeyMethods.ProjectMetadata, authorizedKey.AuthorizationMethod); Assert.AreEqual("bob", authorizedKey.Username); computeEngineAdapter.Verify(a => a.UpdateCommonInstanceMetadataAsync( It.IsAny <string>(), It.IsAny <Action <Metadata> >(), It.IsAny <CancellationToken>()), Times.Once); } }
public async Task WhenCommandIsValid_ThenOpenExecChannelAsyncSucceeds( [LinuxInstance] ResourceTask <InstanceLocator> instanceLocatorTask) { var endpoint = new IPEndPoint( await InstanceUtil.PublicIpAddressForInstanceAsync(await instanceLocatorTask), 22); using (var key = new RsaSshKey(new RSACng())) { await InstanceUtil.AddPublicKeyToMetadata( await instanceLocatorTask, "testuser", key).ConfigureAwait(true); using (var session = CreateSession()) using (var connection = session.Connect(endpoint)) using (var authSession = connection.Authenticate("testuser", key)) using (var channel = authSession.OpenExecChannel( "whoami", LIBSSH2_CHANNEL_EXTENDED_DATA.NORMAL)) { channel.WaitForEndOfStream(); var buffer = new byte[1024]; var bytesRead = channel.Read(buffer); Assert.AreNotEqual(0, bytesRead); Assert.AreEqual("testuser\n", Encoding.ASCII.GetString(buffer, 0, (int)bytesRead)); Assert.AreEqual(0, channel.ExitCode); Assert.IsNull(channel.ExitSignal); channel.Close(); } } }
public async Task WhenSessionDisconnected_ThenAuthenticateThrowsSocketSend( [LinuxInstance] ResourceTask <InstanceLocator> instanceLocatorTask) { var endpoint = new IPEndPoint( await InstanceUtil.PublicIpAddressForInstanceAsync(await instanceLocatorTask), 22); using (var key = new RsaSshKey(new RSACng())) { await InstanceUtil.AddPublicKeyToMetadata( await instanceLocatorTask, "testuser", key); using (var session = CreateSession()) using (var connection = session.Connect(endpoint)) { connection.Dispose(); SshAssert.ThrowsNativeExceptionWithError( session, LIBSSH2_ERROR.SOCKET_SEND, () => connection.Authenticate("testuser", key)); } } }
public async Task WhenNoMoreDataToRead_ThenReadReturnZero( [LinuxInstance] ResourceTask <InstanceLocator> instanceLocatorTask) { var endpoint = new IPEndPoint( await InstanceUtil.PublicIpAddressForInstanceAsync(await instanceLocatorTask), 22); using (var key = new RsaSshKey(new RSACng())) { await InstanceUtil.AddPublicKeyToMetadata( await instanceLocatorTask, "testuser", key).ConfigureAwait(true); using (var session = CreateSession()) using (var connection = session.Connect(endpoint)) using (var authSession = connection.Authenticate( "testuser", key, UnexpectedAuthenticationCallback)) using (var channel = authSession.OpenExecChannel( "whoami", LIBSSH2_CHANNEL_EXTENDED_DATA.NORMAL)) { channel.WaitForEndOfStream(); Assert.AreNotEqual(0, channel.Read(new byte[1024])); Assert.AreEqual(0, channel.Read(new byte[1024])); channel.Close(); } } }
public async Task WhenKeyUnknown_ThenErrorIsShownAndWindowIsClosed( [LinuxInstance] ResourceTask <InstanceLocator> instanceLocatorTask) { var instanceLocator = await instanceLocatorTask; using (var key = new RsaSshKey(new RSACng())) { SessionAbortedEvent deliveredEvent = null; this.eventService.BindHandler <SessionAbortedEvent>(e => deliveredEvent = e); var broker = new SshTerminalSessionBroker( this.serviceProvider); await broker.ConnectAsync( instanceLocator, new IPEndPoint(await PublicAddressFromLocator(instanceLocator), 22), AuthorizedKey.ForMetadata(key, "test", true, null), TimeSpan.FromSeconds(10)) .ConfigureAwait(true); Assert.IsNotNull(deliveredEvent, "Event fired"); Assert.IsInstanceOf(typeof(SshNativeException), this.ExceptionShown); Assert.AreEqual( LIBSSH2_ERROR.AUTHENTICATION_FAILED, ((SshNativeException)this.ExceptionShown).ErrorCode); } }
public async Task WhenDisconnected_ThenOpenExecChannelAsyncThrowsSocketSend( [LinuxInstance] ResourceTask <InstanceLocator> instanceLocatorTask) { var instanceLocator = await instanceLocatorTask; var endpoint = new IPEndPoint( await InstanceUtil.PublicIpAddressForInstanceAsync(await instanceLocatorTask), 22); using (var key = new RsaSshKey(new RSACng())) { await InstanceUtil.AddPublicKeyToMetadata( instanceLocator, "testuser", key).ConfigureAwait(true); using (var session = CreateSession()) using (var connection = session.Connect(endpoint)) using (var authSession = connection.Authenticate("testuser", key)) { connection.Dispose(); SshAssert.ThrowsNativeExceptionWithError( session, LIBSSH2_ERROR.SOCKET_SEND, () => authSession.OpenExecChannel( "whoami", LIBSSH2_CHANNEL_EXTENDED_DATA.NORMAL)); } } }
public async Task WhenConnected_ThenOpenShellChannelAsyncChannelSucceeds( [LinuxInstance] ResourceTask <InstanceLocator> instanceLocatorTask) { var instanceLocator = await instanceLocatorTask; var endpoint = new IPEndPoint( await InstanceUtil.PublicIpAddressForInstanceAsync(await instanceLocatorTask), 22); using (var key = new RsaSshKey(new RSACng())) { await InstanceUtil.AddPublicKeyToMetadata( instanceLocator, "testuser", key).ConfigureAwait(true); using (var session = CreateSession()) using (var connection = session.Connect(endpoint)) using (var authSession = connection.Authenticate("testuser", key)) using (var channel = authSession.OpenExecChannel( "whoami", LIBSSH2_CHANNEL_EXTENDED_DATA.NORMAL)) { channel.Close(); } } }
public async Task WhenServerRejectsLocale_ThenShellUsesDefaultLocale( [LinuxInstance(InitializeScript = "sed -i '/AcceptEnv/d' /etc/ssh/sshd_config && systemctl restart sshd")] ResourceTask <InstanceLocator> instanceLocatorTask) { var endpoint = new IPEndPoint( await InstanceUtil.PublicIpAddressForInstanceAsync(await instanceLocatorTask), 22); using (var key = new RsaSshKey(new RSACng())) { await InstanceUtil.AddPublicKeyToMetadata( await instanceLocatorTask, "testuser", key); var receiveBuffer = new StringBuilder(); void receiveHandler(string data) { lock (receiveBuffer) { receiveBuffer.Append(data); } } using (var connection = new SshShellConnection( "testuser", endpoint, key, SshShellConnection.DefaultTerminal, SshShellConnection.DefaultTerminalSize, new CultureInfo("en-AU"), receiveHandler, exception => { Assert.Fail("Unexpected error"); })) { await connection.ConnectAsync(); AssertEx.ThrowsAggregateException <InvalidOperationException>( () => connection.ConnectAsync().Wait()); await connection.SendAsync("locale;sleep 1;exit\n"); await AwaitBufferContentAsync( receiveBuffer, TimeSpan.FromSeconds(10), "testuser"); StringAssert.Contains( "LC_ALL=\r\n", receiveBuffer.ToString()); } } }
public async Task WhenSendingEchoCommand_ThenEchoIsReceived( [LinuxInstance] ResourceTask <InstanceLocator> instanceLocatorTask) { var endpoint = new IPEndPoint( await InstanceUtil.PublicIpAddressForInstanceAsync(await instanceLocatorTask), 22); using (var key = new RsaSshKey(new RSACng())) { await InstanceUtil.AddPublicKeyToMetadata( await instanceLocatorTask, "testuser", key); var receiveBuffer = new StringBuilder(); void receiveHandler(string data) { lock (receiveBuffer) { receiveBuffer.Append(data); } } using (var connection = new SshShellConnection( "testuser", endpoint, key, SshShellConnection.DefaultTerminal, SshShellConnection.DefaultTerminalSize, CultureInfo.InvariantCulture, receiveHandler, exception => { Assert.Fail("Unexpected error"); })) { await connection.ConnectAsync(); AssertEx.ThrowsAggregateException <InvalidOperationException>( () => connection.ConnectAsync().Wait()); await connection.SendAsync("whoami\n"); await connection.SendAsync("exit\n"); await AwaitBufferContentAsync( receiveBuffer, TimeSpan.FromSeconds(10), "testuser"); StringAssert.Contains( "testuser", receiveBuffer.ToString()); } } }
public async Task WhenLocaleIsNull_ThenShellUsesDefaultLocale( [LinuxInstance] ResourceTask <InstanceLocator> instanceLocatorTask) { var endpoint = new IPEndPoint( await InstanceUtil.PublicIpAddressForInstanceAsync(await instanceLocatorTask), 22); using (var key = new RsaSshKey(new RSACng())) { await InstanceUtil.AddPublicKeyToMetadata( await instanceLocatorTask, "testuser", key); var receiveBuffer = new StringBuilder(); void receiveHandler(string data) { lock (receiveBuffer) { receiveBuffer.Append(data); } } using (var connection = new SshShellConnection( "testuser", endpoint, key, SshShellConnection.DefaultTerminal, SshShellConnection.DefaultTerminalSize, null, UnexpectedAuthenticationCallback, receiveHandler, UnexpectedErrorCallback)) { await connection.ConnectAsync(); AssertEx.ThrowsAggregateException <InvalidOperationException>( () => connection.ConnectAsync().Wait()); await connection.SendAsync("locale;sleep 1;exit\n"); await AwaitBufferContentAsync( receiveBuffer, TimeSpan.FromSeconds(10), "testuser"); StringAssert.Contains( "LC_ALL=\r\n", receiveBuffer.ToString()); } } }
public async Task WhenConnected_ThenTryActivateReturnsTrue( [LinuxInstance] ResourceTask <InstanceLocator> testInstance, [Credential(Role = PredefinedRole.ComputeInstanceAdminV1)] ResourceTask <ICredential> credential) { var locator = await testInstance; using (var key = new RsaSshKey(new RSACng())) using (var gceAdapter = new ComputeEngineAdapter( this.serviceProvider.GetService <IAuthorizationAdapter>())) using (var keyAdapter = new AuthorizedKeyService( this.serviceProvider.GetService <IAuthorizationAdapter>(), new ComputeEngineAdapter(await credential), new ResourceManagerAdapter(await credential), new Mock <IOsLoginService>().Object)) { var authorizedKey = await keyAdapter.AuthorizeKeyAsync( locator, key, TimeSpan.FromMinutes(10), null, AuthorizeKeyMethods.InstanceMetadata, CancellationToken.None) .ConfigureAwait(true); var instance = await gceAdapter.GetInstanceAsync( locator, CancellationToken.None) .ConfigureAwait(true); // Connect var broker = new SshTerminalSessionBroker(this.serviceProvider); ISshTerminalSession session = null; await AssertRaisesEventAsync <SessionStartedEvent>( async() => session = await broker.ConnectAsync( locator, new IPEndPoint(instance.PublicAddress(), 22), authorizedKey, null, TimeSpan.FromSeconds(10))); Assert.IsNull(this.ExceptionShown); Assert.AreSame(session, SshTerminalPane.TryGetActivePane(this.mainForm)); Assert.AreSame(session, SshTerminalPane.TryGetExistingPane(this.mainForm, locator)); Assert.IsTrue(broker.IsConnected(locator)); Assert.IsTrue(broker.TryActivate(locator)); AssertRaisesEvent <SessionEndedEvent>( () => session.Close()); } }
public async Task WhenExistingInvalidManagedKeyFound_ThenNewKeyIsPushed() { using (var key = RsaSshKey.NewEphemeralKey()) { var existingProjectKeySet = MetadataAuthorizedKeySet .FromMetadata(new Metadata()) .Add(new ManagedMetadataAuthorizedKey( "bob", "ssh-rsa", key.PublicKeyString, new ManagedKeyMetadata(SampleEmailAddress, DateTime.UtcNow.AddMinutes(-5)))); var computeEngineAdapter = CreateComputeEngineAdapterMock( osLoginEnabledForProject: false, osLoginEnabledForInstance: false, osLogin2fa: false, legacySshKeyPresent: false, projectWideKeysBlockedForProject: false, projectWideKeysBlockedForInstance: false, existingProjectKeySet: existingProjectKeySet, existingInstanceKeySet: null); var service = new AuthorizedKeyService( CreateAuthorizationAdapterMock().Object, computeEngineAdapter.Object, CreateResourceManagerAdapterMock(true).Object, CreateOsLoginServiceMock().Object); var authorizedKey = await service.AuthorizeKeyAsync( SampleLocator, key, TimeSpan.FromMinutes(1), "bob", AuthorizeKeyMethods.All, CancellationToken.None); Assert.IsNotNull(authorizedKey); Assert.AreEqual(AuthorizeKeyMethods.ProjectMetadata, authorizedKey.AuthorizationMethod); Assert.AreEqual("bob", authorizedKey.Username); computeEngineAdapter.Verify(a => a.UpdateMetadataAsync( It.IsAny <InstanceLocator>(), It.IsAny <Action <Metadata> >(), It.IsAny <CancellationToken>()), Times.Never); computeEngineAdapter.Verify(a => a.UpdateCommonInstanceMetadataAsync( It.IsAny <string>(), It.IsAny <Action <Metadata> >(), It.IsAny <CancellationToken>()), Times.Once); } }
public async Task WhenPseudoterminalResized_ThenShellReflectsNewSize( [LinuxInstance] ResourceTask <InstanceLocator> instanceLocatorTask) { var endpoint = new IPEndPoint( await InstanceUtil.PublicIpAddressForInstanceAsync(await instanceLocatorTask), 22); using (var key = new RsaSshKey(new RSACng())) { await InstanceUtil.AddPublicKeyToMetadata( await instanceLocatorTask, "testuser", key).ConfigureAwait(true); using (var session = CreateSession()) using (var connection = session.Connect(endpoint)) using (var authSession = connection.Authenticate( "testuser", key, UnexpectedAuthenticationCallback)) using (var channel = authSession.OpenShellChannel( LIBSSH2_CHANNEL_EXTENDED_DATA.MERGE, DefaultTerminal, 80, 24)) { var welcome = ReadUntil(channel, "~$", Encoding.ASCII); // Read initial terminal size. channel.Write(Encoding.ASCII.GetBytes("echo $COLUMNS $LINES\n")); ReadUntil(channel, "\n", Encoding.ASCII); var terminalSize = ReadUntil(channel, "\n", Encoding.ASCII); Assert.AreEqual("80 24\r\n", terminalSize); // Resize terminal. channel.ResizePseudoTerminal(100, 30); // Read terminal size again. channel.Write(Encoding.ASCII.GetBytes("echo $COLUMNS $LINES\n")); ReadUntil(channel, "\n", Encoding.ASCII); terminalSize = ReadUntil(channel, "\n", Encoding.ASCII); Assert.AreEqual("100 30\r\n", terminalSize); channel.Close(); } } }
private async Task <SshTerminalPane> ConnectSshTerminalPane( InstanceLocator instanceLocator, ICredential credential) { var authorization = new Mock <IAuthorization>(); authorization .SetupGet(a => a.Email) .Returns("*****@*****.**"); var authorizationAdapter = new Mock <IAuthorizationAdapter>(); authorizationAdapter .Setup(a => a.Authorization) .Returns(authorization.Object); using (var key = new RsaSshKey(new RSACng())) using (var keyAdapter = new AuthorizedKeyService( authorizationAdapter.Object, new ComputeEngineAdapter(credential), new ResourceManagerAdapter(credential), new Mock <IOsLoginService>().Object)) { var authorizedKey = await keyAdapter.AuthorizeKeyAsync( instanceLocator, key, TimeSpan.FromMinutes(10), null, AuthorizeKeyMethods.InstanceMetadata, CancellationToken.None) .ConfigureAwait(true); // Connect and wait for event SessionStartedEvent connectedEvent = null; this.eventService.BindHandler <SessionStartedEvent>(e => connectedEvent = e); var broker = new SshTerminalSessionBroker( this.serviceProvider); var pane = await broker.ConnectAsync( instanceLocator, new IPEndPoint(await PublicAddressFromLocator(instanceLocator), 22), authorizedKey) .ConfigureAwait(true); Assert.IsNotNull(connectedEvent, "ConnectionSuceededEvent event fired"); PumpWindowMessages(); return((SshTerminalPane)pane); } }
public async Task WhenWhitelistedEnvironmentVariablePassed_ThenShellCanAccessVariable( [LinuxInstance] ResourceTask <InstanceLocator> instanceLocatorTask) { var endpoint = new IPEndPoint( await InstanceUtil.PublicIpAddressForInstanceAsync(await instanceLocatorTask), 22); using (var key = new RsaSshKey(new RSACng())) { await InstanceUtil.AddPublicKeyToMetadata( await instanceLocatorTask, "testuser", key).ConfigureAwait(true); using (var session = CreateSession()) using (var connection = session.Connect(endpoint)) using (var authSession = connection.Authenticate( "testuser", key, UnexpectedAuthenticationCallback)) using (var channel = authSession.OpenShellChannel( LIBSSH2_CHANNEL_EXTENDED_DATA.MERGE, DefaultTerminal, 80, 24, new[] { new EnvironmentVariable( "LANG", "LC_ALL", true) // LANG is whitelisted by sshd by default. })) { var bytesWritten = channel.Write(Encoding.ASCII.GetBytes("echo $LANG;exit\n")); Assert.AreEqual(16, bytesWritten); var output = ReadToEnd(channel, Encoding.ASCII); channel.Close(); StringAssert.Contains( "en_US.UTF-8", output); Assert.AreEqual(0, channel.ExitCode); } } }
public async Task WhenPublicKeyValidButUnrecognized_ThenAuthenticateThrowsAuthenticationFailed( [LinuxInstance] ResourceTask <InstanceLocator> instanceLocatorTask) { var endpoint = new IPEndPoint( await InstanceUtil.PublicIpAddressForInstanceAsync(await instanceLocatorTask), 22); using (var session = CreateSession()) using (var connection = session.Connect(endpoint)) using (var key = new RsaSshKey(new RSACng())) { SshAssert.ThrowsNativeExceptionWithError( session, LIBSSH2_ERROR.AUTHENTICATION_FAILED, () => connection.Authenticate("invaliduser", key)); } }
public async Task WhenConnected_ThenOpenShellChannelAsyncSucceeds( [LinuxInstance] ResourceTask <InstanceLocator> instanceLocatorTask) { var endpoint = new IPEndPoint( await InstanceUtil.PublicIpAddressForInstanceAsync(await instanceLocatorTask), 22); using (var key = new RsaSshKey(new RSACng())) { await InstanceUtil.AddPublicKeyToMetadata( await instanceLocatorTask, "testuser", key).ConfigureAwait(true); using (var session = CreateSession()) using (var connection = session.Connect(endpoint)) using (var authSession = connection.Authenticate( "testuser", key, UnexpectedAuthenticationCallback)) using (var channel = authSession.OpenShellChannel( LIBSSH2_CHANNEL_EXTENDED_DATA.MERGE, DefaultTerminal, 80, 24)) { // Run command. var bytesWritten = channel.Write(Encoding.ASCII.GetBytes("whoami;exit\n")); Assert.AreEqual(12, bytesWritten); // Read command output. var output = ReadToEnd(channel, Encoding.ASCII); channel.Close(); StringAssert.Contains( "whoami;exit\r\ntestuser\r\nlogout\r\n", output); Assert.AreEqual(0, channel.ExitCode); Assert.AreEqual(null, channel.ExitSignal); } } }
public async Task WhenCommandInvalidAndExtendedDataModeIsNormal_ThenExecuteSucceedsAndStderrContainsError( [LinuxInstance] ResourceTask <InstanceLocator> instanceLocatorTask) { var endpoint = new IPEndPoint( await InstanceUtil.PublicIpAddressForInstanceAsync(await instanceLocatorTask), 22); using (var key = new RsaSshKey(new RSACng())) { await InstanceUtil.AddPublicKeyToMetadata( await instanceLocatorTask, "testuser", key).ConfigureAwait(true); using (var session = CreateSession()) using (var connection = session.Connect(endpoint)) using (var authSession = connection.Authenticate( "testuser", key, UnexpectedAuthenticationCallback)) using (var channel = authSession.OpenExecChannel( "invalidcommand", LIBSSH2_CHANNEL_EXTENDED_DATA.NORMAL)) { channel.WaitForEndOfStream(); var buffer = new byte[1024]; var bytesRead = channel.Read( buffer, LIBSSH2_STREAM.EXTENDED_DATA_STDERR); Assert.AreNotEqual(0, bytesRead); Assert.AreEqual( "bash: invalidcommand: command not found\n", Encoding.ASCII.GetString(buffer, 0, (int)bytesRead)); Assert.AreEqual(127, channel.ExitCode); Assert.IsNull(channel.ExitSignal); channel.Close(); } } }
public void WhenMetadataUpdatesFails_ThenAuthorizeKeyAsyncThrowsSshKeyPushFailedException( [Values( HttpStatusCode.Forbidden, HttpStatusCode.BadRequest)] HttpStatusCode httpStatus) { var computeEngineAdapter = CreateComputeEngineAdapterMock( osLoginEnabledForProject: null, osLoginEnabledForInstance: null, osLogin2fa: false, legacySshKeyPresent: false, projectWideKeysBlockedForProject: false, projectWideKeysBlockedForInstance: false); computeEngineAdapter .Setup(a => a.UpdateCommonInstanceMetadataAsync( It.IsAny <string>(), It.IsAny <Action <Metadata> >(), It.IsAny <CancellationToken>())) .Throws(new GoogleApiException("GCE", "mock-error") { HttpStatusCode = httpStatus }); var service = new AuthorizedKeyService( CreateAuthorizationAdapterMock().Object, computeEngineAdapter.Object, CreateResourceManagerAdapterMock(true).Object, CreateOsLoginServiceMock().Object); using (var key = RsaSshKey.NewEphemeralKey()) { AssertEx.ThrowsAggregateException <SshKeyPushFailedException>( () => service.AuthorizeKeyAsync( SampleLocator, key, TimeSpan.FromMinutes(1), null, AuthorizeKeyMethods.All, CancellationToken.None).Wait()); } }
public async Task WhenWrongPort_ThenErrorIsShownAndWindowIsClosed() { using (var key = new RsaSshKey(new RSACng())) { SessionAbortedEvent deliveredEvent = null; this.eventService.BindHandler <SessionAbortedEvent>(e => deliveredEvent = e); var broker = new SshTerminalSessionBroker( this.serviceProvider); await broker.ConnectAsync( new InstanceLocator("project-1", "zone-1", "instance-1"), NonSshEndpoint, AuthorizedKey.ForMetadata(key, "test", true, null)) .ConfigureAwait(true); Assert.IsNotNull(deliveredEvent, "Event fired"); Assert.IsInstanceOf(typeof(SocketException), this.ExceptionShown); Assert.AreEqual( SocketError.ConnectionRefused, ((SocketException)this.ExceptionShown).SocketErrorCode); } }
public async Task When2faRequiredAndPromptReturnsNull_ThenPromptIsRetried( [LinuxInstance(InitializeScript = RequireSshPassword)] ResourceTask <InstanceLocator> instanceLocatorTask) { var endpoint = new IPEndPoint( await InstanceUtil.PublicIpAddressForInstanceAsync(await instanceLocatorTask), 22); using (var key = new RsaSshKey(new RSACng())) { await InstanceUtil.AddPublicKeyToMetadata( await instanceLocatorTask, "testuser", key); using (var session = CreateSession()) using (var connection = session.Connect(endpoint)) { var callbackCount = 0; SshAssert.ThrowsNativeExceptionWithError( session, LIBSSH2_ERROR.AUTHENTICATION_FAILED, () => connection.Authenticate( "testuser", key, (name, instruction, prompt, echo) => { callbackCount++; Assert.AreEqual("Password: ", prompt); Assert.IsFalse(echo); return(null); })); Assert.AreEqual(SshConnectedSession.KeyboardInteractiveRetries, callbackCount); } } }
//--------------------------------------------------------------------- // ISshConnectionService. //--------------------------------------------------------------------- public async Task ActivateOrConnectInstanceAsync(IProjectModelInstanceNode vmNode) { Debug.Assert(vmNode.IsSshSupported()); if (this.sessionBroker.TryActivate(vmNode.Instance)) { // SSH session was active, nothing left to do. return; } // Select node so that tracking windows are updated. await this.projectModelService.SetActiveNodeAsync( vmNode, CancellationToken.None) .ConfigureAwait(true); var instance = vmNode.Instance; var settings = (InstanceConnectionSettings)this.settingsService .GetConnectionSettings(vmNode) .TypedCollection; var timeout = TimeSpan.FromSeconds(settings.SshConnectionTimeout.IntValue); // // Start job to create IAP tunnel. // var tunnelTask = this.jobService.RunInBackground( new JobDescription( $"Opening Cloud IAP tunnel to {instance.Name}...", JobUserFeedbackType.BackgroundFeedback), async token => { try { var destination = new TunnelDestination( vmNode.Instance, (ushort)settings.SshPort.IntValue); // NB. Give IAP the same timeout for probing as SSH itself. return(await this.tunnelBroker.ConnectAsync( destination, new SameProcessRelayPolicy(), timeout) .ConfigureAwait(false)); } catch (NetworkStreamClosedException e) { throw new ConnectionFailedException( "Connecting to the instance failed. Make sure that you have " + "configured your firewall rules to permit Cloud IAP access " + $"to {instance.Name}", HelpTopics.CreateIapFirewallRule, e); } catch (UnauthorizedException) { throw new ConnectionFailedException( "You are not authorized to connect to this VM instance.\n\n" + $"Verify that the Cloud IAP API is enabled in the project {instance.ProjectId} " + "and that your user has the 'IAP-secured Tunnel User' role.", HelpTopics.IapAccess); } }); // // Load persistent CNG key. This must be done on the UI thread. // var email = this.authorizationAdapter.Authorization.Email; var rsaKey = this.keyStoreAdapter.CreateRsaKey( $"IAPDESKTOP_{email}", CngKeyUsages.Signing, true, this.window); Debug.Assert(rsaKey != null); // // Start job to publish key, using whatever mechanism is appropriate // for this instance. // var sshKey = new RsaSshKey(rsaKey); try { var sshSettings = this.sshSettingsRepository.GetSettings(); var authorizedKeyTask = this.jobService.RunInBackground( new JobDescription( $"Publishing SSH key for {instance.Name}...", JobUserFeedbackType.BackgroundFeedback), async token => { // // Authorize the key. // return(await this.authorizedKeyService.AuthorizeKeyAsync( vmNode.Instance, sshKey, TimeSpan.FromSeconds(sshSettings.PublicKeyValidity.IntValue), NullIfEmpty(settings.SshUsername.StringValue), AuthorizeKeyMethods.All, token) .ConfigureAwait(true)); }); // // Wait for both jobs to continue (they are both fairly slow). // await Task.WhenAll(tunnelTask, authorizedKeyTask) .ConfigureAwait(true); var language = sshSettings.IsPropagateLocaleEnabled.BoolValue ? CultureInfo.CurrentUICulture : null; // // NB. ConnectAsync takes ownership of the key and will retain // it for the lifetime of the session. // await this.sessionBroker.ConnectAsync( instance, new IPEndPoint(IPAddress.Loopback, tunnelTask.Result.LocalPort), authorizedKeyTask.Result, language, timeout) .ConfigureAwait(true); } catch (Exception) { sshKey.Dispose(); throw; } }