public async Task <NetworkCredential> GenerateAndSaveCredentialsAsync( IWin32Window owner, VmInstanceNode vmNode, string suggestedUsername = null) { var credentials = await GenerateCredentialsAsync( owner, vmNode.Reference, suggestedUsername ?? this.authService.Authorization.SuggestWindowsUsername()); if (credentials == null) { // Aborted. return(null); } // Update node to persist settings. vmNode.Username = credentials.UserName; vmNode.CleartextPassword = credentials.Password; vmNode.Domain = null; vmNode.SaveChanges(); // Fire an event to update anybody using the node. await this.eventService.FireAsync(new ProjectExplorerNodeSelectedEvent(vmNode)); return(credentials); }
public async Task ActivateOrConnectInstanceWithCredentialPromptAsync( IWin32Window owner, VmInstanceNode vmNode) { if (this.remoteDesktopService.TryActivate(vmNode.Reference)) { // RDP session was active, nothing left to do. return; } // Select node so that tracking windows are updated. vmNode.Select(); var settings = vmNode.SettingsEditor; if (string.IsNullOrEmpty(settings.Username) || settings.Password == null || settings.Password.Length == 0) { int selectedOption = this.taskDialog.ShowOptionsTaskDialog( owner, UnsafeNativeMethods.TD_INFORMATION_ICON, "Credentials", $"You have not configured any credentials for {vmNode.InstanceName}", "Would you like to configure or generate credentials now?", null, new[] { "Configure credentials", "Generate new credentials", // Same as pressing 'OK' "Connect anyway" // Same as pressing 'Cancel' }, null, //"Do not show this prompt again", out bool donotAskAgain); if (selectedOption == 0) { // Configure credentials -> jump to settings. this.settingsEditor.ShowWindow(); return; } else if (selectedOption == 1) { // Generate new credentials. await this.credentialsService.GenerateCredentialsAsync( owner, vmNode.Reference, vmNode.SettingsEditor) .ConfigureAwait(true); } else if (selectedOption == 2) { // Cancel - just continue connecting. } } await ConnectInstanceAsync( vmNode.Reference, vmNode.CreateConnectionSettings()) .ConfigureAwait(true); }
private async Task GenerateCredentials(VmInstanceNode vmNode) { // Derive a suggested username from the Windows login name. var suggestedUsername = Environment.UserName; // Prompt for username to use. var username = new GenerateCredentialsDialog().PromptForUsername(this, suggestedUsername); if (username == null) { return; } var credentials = await this.jobService.RunInBackground( new JobDescription("Generating Windows logon credentials..."), token => { return(this.serviceProvider.GetService <IComputeEngineAdapter>() .ResetWindowsUserAsync(vmNode.Reference, username, token)); }); new ShowCredentialsDialog().ShowDialog( this, credentials.UserName, credentials.Password); // Update node to persist settings. vmNode.Username = credentials.UserName; vmNode.CleartextPassword = credentials.Password; vmNode.Domain = null; vmNode.SaveChanges(); // Fire an event to update anybody using the node. await this.eventService.FireAsync(new ProjectExplorerNodeSelectedEvent(vmNode)); }
public void Populate( IEnumerable <Instance> allInstances, Func <InstanceLocator, bool> isConnected) { this.Nodes.Clear(); // Narrow the list down to Windows instances - there is no point // of adding Linux instanes to the list of servers. var instances = allInstances.Where(i => ComputeEngineAdapter.IsWindowsInstance(i)); var zoneIds = instances.Select(i => InventoryNode.ShortIdFromUrl(i.Zone)).ToHashSet(); foreach (var zoneId in zoneIds) { var zoneSettings = this.settingsRepository.GetZoneSettings( this.ProjectId, zoneId); var zoneNode = new ZoneNode( zoneSettings, changedSettings => this.settingsRepository.SetZoneSettings(this.ProjectId, changedSettings), this); var instancesInZone = instances .Where(i => InventoryNode.ShortIdFromUrl(i.Zone) == zoneId) .OrderBy(i => i.Name); foreach (var instance in instancesInZone) { var instanceSettings = this.settingsRepository.GetVmInstanceSettings( this.ProjectId, instance.Name); var instanceNode = new VmInstanceNode( instance, instanceSettings, changedSettings => this.settingsRepository.SetVmInstanceSettings(this.ProjectId, changedSettings), zoneNode); instanceNode.IsConnected = isConnected( new InstanceLocator(this.ProjectId, zoneId, instance.Name)); zoneNode.Nodes.Add(instanceNode); } this.Nodes.Add(zoneNode); zoneNode.Expand(); } Expand(); }
private async Task ConnectInstance(VmInstanceNode vmNode) { if (this.remoteDesktopService.TryActivate(vmNode.Reference)) { // RDP session was already open, nothing left to do. return; } var destination = new TunnelDestination(vmNode.Reference, RemoteDesktopPort); // TODO: make configurable var timeout = TimeSpan.FromSeconds(30); var tunnel = await this.jobService.RunInBackground( new JobDescription("Opening Cloud IAP tunnel..."), async token => { try { var tunnelBrokerService = this.serviceProvider.GetService <TunnelBrokerService>(); return(await tunnelBrokerService.ConnectAsync(destination, timeout)); } catch (NetworkStreamClosedException e) { throw new ApplicationException( "Connecting to the instance failed. Make sure that you have " + "configured your firewall rules to permit Cloud IAP access " + $"to {vmNode.InstanceName}", e); } catch (UnauthorizedException) { throw new ApplicationException( "You are not authorized to connect to this VM instance.\n\n" + $"Verify that the Cloud IAP API is enabled in the project {vmNode.Reference.ProjectId} " + "and that your user has the 'IAP-secured Tunnel User' role."); } }); this.remoteDesktopService.Connect( vmNode.Reference, "localhost", (ushort)tunnel.LocalPort, vmNode.EffectiveSettingsWithInheritanceApplied); }