/// <summary> /// Creates the specified resources. /// </summary> /// <param name="resources">The resources.</param> /// <param name="manifest">The manifest.</param> internal override void AddToManifest(Collection <VirtualResource> resources, SystemManifest manifest) { // Iterate through each resource and create the office worker process foreach (VirtualResource resource in resources) { // First determine if the resource already exists in the Resource collection. If not, then // have VirtualResource create it, then update it with other data and add it to the list. var detail = manifest.Resources.GetResource <AdminWorkerDetail>(resource.VirtualResourceId); if (detail == null) { detail = (AdminWorkerDetail)CreateDetail(resource); detail.CommandPortOffset = 40000; manifest.Resources.Add(detail); } // Use the system settings Administrator credentials for the AdminWorker var userCredential = new OfficeWorkerCredential(); userCredential.UserName = GlobalSettings.Items[Setting.DomainAdminUserName]; userCredential.Password = GlobalSettings.Items[Setting.DomainAdminPassword]; userCredential.Domain = GlobalSettings.Items[Setting.Domain]; userCredential.Port = detail.CommandPortOffset; // This only works with just the username because there is only one // allowed per VM. If this ever changes then there will need to be a // unique suffix added. //userCredential.InstanceId = SystemManifestAgent.CreateUniqueId(userCredential.UserName); userCredential.ResourceInstanceId = userCredential.UserName; detail.UserCredentials.Add(userCredential); } }
protected void LoadResources <T>(Collection <VirtualResource> resources, SystemManifest manifest) where T : OfficeWorkerDetail { // Iterate through each resource and create the office worker process foreach (var resource in resources) { // First determine if the resource already exists in the Resource collection. If not, then // have VirtualResource create it, then update it with other data and add it to the list. var detail = manifest.Resources.GetResource <T>(resource.VirtualResourceId); if (detail == null) { detail = (T)CreateDetail(resource); detail.OfficeWorkerCount = ResourcePacker.TotalResourceCount(ResourceType); detail.StartIndex = ManifestAgent.UserAccounts.StartIndex(((OfficeWorker)resource).UserPool); detail.UserNameFormat = ManifestAgent.UserAccounts.UserFormat(((OfficeWorker)resource).UserPool); detail.CommandPortOffset = 40000; manifest.Resources.Add(detail); } // Get the next credential and add it to the OW definition OfficeWorkerCredential credential = AddCredential(resource, detail); detail.UserCredentials.Add(credential); // Add any external credentials associated with the OW credential AddExternalCredentials(credential, detail); } }
/// <summary> /// Creates resource detail and inserts it into the manifest. /// </summary> /// <param name="resources">The resources.</param> /// <param name="manifest">The manifest.</param> internal override void AddToManifest(Collection <VirtualResource> resources, SystemManifest manifest) { // There is one Load Tester per VM, so there should only be one // resource embedded in this manifest. var resource = resources.First(); // First determine if the resource already exists in the Resource collection. If not, then // have VirtualResource create it, then update it with other data and add it to the list. var detail = manifest.Resources.GetResource <LoadTesterDetail>(resource.VirtualResourceId); if (detail == null) { detail = CreateDetail(resource); detail.CommandPortOffset = 40000; manifest.Resources.Add(detail); } // Use the system settings Administrator credentials for the AdminWorker var userCredential = new OfficeWorkerCredential(); userCredential.UserName = GlobalSettings.Items[Setting.DomainAdminUserName]; userCredential.Password = GlobalSettings.Items[Setting.DomainAdminPassword]; userCredential.Domain = GlobalSettings.Items[Setting.Domain]; userCredential.Port = detail.CommandPortOffset; userCredential.ResourceInstanceId = SystemManifestAgent.CreateUniqueId(userCredential.UserName); detail.UserCredentials.Add(userCredential); }
internal static string CreateIcaFile(OfficeWorkerCredential credential, string citrixServer, string publishedApp) { // Create the ICA Client file using the template, then launch the ICA Client against the template, this will // start the published app on the Citrix server. string template = Resources.CitrixWorkerXenApp.FormatWith ( credential.Domain.Split('.').First(), credential.UserName, credential.Password, citrixServer, publishedApp ); TraceFactory.Logger.Debug(Environment.NewLine + template); if (!Directory.Exists(Resources.ICAFilePath)) { Directory.CreateDirectory(Resources.ICAFilePath); } // Write the ICA File out to a temp location string citrixIcaFile = Path.Combine(Resources.ICAFilePath, Resources.ICAFile.FormatWith(credential.UserName)); TraceFactory.Logger.Debug("ICA File: {0}".FormatWith(citrixIcaFile)); File.WriteAllText(citrixIcaFile, template); if (!File.Exists(citrixIcaFile)) { throw new IOException("ICA File not created"); } return(citrixIcaFile); }
internal override OfficeWorkerCredential AddCredential(VirtualResource resource, OfficeWorkerDetail detail) { SolutionTester tester = resource as SolutionTester; OfficeWorkerCredential credential = null; switch (tester.AccountType) { case SolutionTesterCredentialType.AccountPool: credential = ManifestAgent.UserAccounts.NextUserCredential(((OfficeWorker)resource).UserPool); credential.ResourceInstanceId = credential.UserName; //credential.ResourceInstanceId = SystemManifestAgent.CreateUniqueId(credential.UserName); break; case SolutionTesterCredentialType.DefaultDesktop: credential = new OfficeWorkerCredential(); credential.Domain = Environment.UserDomainName; credential.UserName = Environment.UserName; credential.Password = string.Empty; credential.ResourceInstanceId = SystemManifestAgent.CreateUniqueId(Environment.UserName); break; case SolutionTesterCredentialType.ManuallyEntered: credential = new OfficeWorkerCredential(); credential.Domain = tester.Domain; credential.UserName = tester.UserName; credential.Password = tester.Password; credential.ResourceInstanceId = SystemManifestAgent.CreateUniqueId(tester.UserName); break; } return(credential); }
/// <summary> /// Calls the print UI utility. /// </summary> /// <param name="printerPath">The printer path.</param> /// <param name="credential">The credential.</param> private static void CallPrintUi(string printerPath, OfficeWorkerCredential credential = null) { string arg = Resources.PrintUICommand.FormatWith(printerPath); TraceFactory.Logger.Debug(arg); CitrixSessionManager.StartProcess(credential, "CMD.EXE", arg, TimeSpan.FromMinutes(10)); }
/// <summary> /// Starts the SolutionTester process for the specified credential. /// </summary> /// <param name="credential">The user credential.</param> /// <param name="currentDirectory">The current directory.</param> protected override void StartUserProcess(OfficeWorkerCredential credential, string currentDirectory) { string root = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string exeFile = Properties.Resources.SolutionTesterApplicationFileName; var solutionTester = Path.Combine(Path.GetDirectoryName(root), exeFile); if (!File.Exists(solutionTester)) { solutionTester = "C:\\VirtualResource\\Distribution\\SolutionTesterConsole\\SolutionTesterConsole.exe"; } try { SolutionTesterDetail detail = GlobalDataStore.Manifest.Resources.GetWorker <SolutionTesterDetail>(credential.ResourceInstanceId); if (detail.UseCredential) { // The solution tester should be started using the same credentials // that will be available to each plugin that executes. TraceFactory.Logger.Debug("Starting SolutionTester using account for {0}".FormatWith(credential.UserName)); var commandLine = "{0} {1}".FormatWith ( credential.ResourceInstanceId, SystemManifest.SessionId ); NetworkCredential netCredential = new NetworkCredential(credential.UserName, credential.Password, credential.Domain); ProcessUtil.Launch(solutionTester, commandLine, currentDirectory, netCredential); } else { // The solution tester should be started using the default destop account. TraceFactory.Logger.Debug("Starting SolutionTester using Desktop account"); string args = "{0} {1}".FormatWith ( credential.ResourceInstanceId, SystemManifest.SessionId ); ProcessStartInfo info = new ProcessStartInfo(solutionTester, args); info.LoadUserProfile = true; info.UseShellExecute = true; info.WindowStyle = ProcessWindowStyle.Minimized; info.WorkingDirectory = Path.GetDirectoryName(solutionTester); TraceFactory.Logger.Debug("{0} {1}".FormatWith(solutionTester, args)); Process.Start(info); } } catch (Exception ex) { TraceFactory.Logger.Fatal("Failed to create process.", ex); throw; } ChangeMachineStatusMessage("Tester started"); TraceFactory.Logger.Debug("Start User Process Complete".FormatWith(credential.UserName, credential.Port)); }
internal virtual OfficeWorkerCredential AddCredential(VirtualResource resource, OfficeWorkerDetail detail) { // Get the next credential and add it to the OW definition OfficeWorkerCredential credential = ManifestAgent.UserAccounts.NextUserCredential(((OfficeWorker)resource).UserPool); credential.Port = detail.CommandPortOffset + credential.Port; credential.ResourceInstanceId = credential.UserName; return(credential); }
/// <summary> /// Starts the defined Virtual Resource process for the defined credential. /// </summary> /// <param name="credential">The user credential.</param> /// <param name="currentDirectory">The current directory.</param> protected override void StartUserProcess(OfficeWorkerCredential credential, string currentDirectory) { if (credential == null) { throw new ArgumentNullException("credential"); } Environment.SpecialFolder folder = (Environment.Is64BitOperatingSystem) ? Environment.SpecialFolder.ProgramFilesX86 : Environment.SpecialFolder.ProgramFiles; var exeFile = Path.Combine ( Environment.GetFolderPath(folder), Resources.WFICA32Path ); TraceFactory.Logger.Debug("ICA Client: {0}".FormatWith(exeFile)); int tries = 0; int numTries = 5; while (tries < numTries) { if (CheckSessionStarted(credential, exeFile)) { break; } tries++; TraceFactory.Logger.Debug("Failed to start session, sleeping and trying again"); if (!ProcessUtil.KillProcess(Resources.wfica32, currentUserOnly: false)) { TraceFactory.Logger.Debug("Failed to kill ICA process"); } else { TraceFactory.Logger.Debug("ICA process killed"); } // Kill any session on the Citrix server CitrixSessionManager.ResetCitrixSession(credential.UserName, _citrixServer); Thread.Sleep(TimeSpan.FromSeconds(5)); } if (tries >= numTries) { throw new ArgumentException("Unable to start Citrix process after {0} tries, for {1}".FormatWith(numTries, credential.UserName)); } else { TraceFactory.Logger.Debug("Citrix session started"); } }
/// <summary> /// Removes the user from Administrator group of the local machine /// </summary> /// <param name="credential"></param> internal static void RemoveUserFromGroup(OfficeWorkerCredential credential) { PrincipalContext domainContext = new PrincipalContext(ContextType.Domain, credential.Domain); UserPrincipal user = UserPrincipal.FindByIdentity(domainContext, credential.UserName); PrincipalContext userContext = new PrincipalContext(ContextType.Machine, Environment.MachineName); GroupPrincipal administrators = GroupPrincipal.FindByIdentity(userContext, "Administrators"); ActiveDirectoryController.RemoveUserFromGroup(user, administrators); }
/// <summary> /// Cleans up the specified user profile path. /// </summary> /// <param name="credential">The user id.</param> public static void Cleanup(OfficeWorkerCredential credential) { //if the credential is same as the current user then ignore if (credential.UserName == Environment.UserName) { return; } ThreadPool.QueueUserWorkItem(t => CleanupUserProfile(credential)); }
internal virtual void AddExternalCredentials(OfficeWorkerCredential domainCredential, OfficeWorkerDetail officeWorkerDetail) { using (AssetInventoryContext context = new AssetInventoryContext(DbConnect.AssetInventoryConnectionString)) { foreach (ExternalCredential extCredential in context.ExternalCredentials.Where(x => x.DomainUserName == domainCredential.UserName)) { officeWorkerDetail.ExternalCredentials.Add(new ExternalCredentialDetail(extCredential.UserName, extCredential.Password, extCredential.ExternalCredentialType, extCredential.DomainUserName)); } } }
internal static void RestartCitrixClient(OfficeWorkerCredential credential) { TraceFactory.Logger.Debug(@"{0}\{1}".FormatWith(credential.Domain, credential.UserName)); // This will kill the Citrix client process, typically running under admin and // restart it under the target username. if (credential == null) { throw new ArgumentNullException("credential"); } int tries = 0; bool done = false; // ALAN: Consider re-designing such that StartProcess throws an exception on failure...then this can be // done via the RetryUtil. do { // First kill the wfcrun32 process as it will be restarted under the target username if (!ProcessUtil.KillProcess(Resources.wfcrun32, currentUserOnly: false)) { TraceFactory.Logger.Debug("Failed to kill current process"); } else { TraceFactory.Logger.Debug("Current process killed"); } Environment.SpecialFolder folder = (Environment.Is64BitOperatingSystem) ? Environment.SpecialFolder.ProgramFilesX86 : Environment.SpecialFolder.ProgramFiles; string citrixClient = Path.Combine(Environment.GetFolderPath(folder), Resources.WFCRun32Path); TraceFactory.Logger.Debug("Starting {0}".FormatWith(citrixClient)); if (!StartProcess(credential, citrixClient, string.Empty, TimeSpan.FromSeconds(10), true)) { tries++; } else { done = true; } } while (tries < 3 && !done); if (!done) { throw new InvalidOperationException("Unable to start process"); } TraceFactory.Logger.Debug("Process started"); }
internal static void RemoveFromAdminGroup(OfficeWorkerCredential credential, string citrixServer) { // Remove this user from the Administrators group. TraceFactory.Logger.Debug("Removing {0} from Administrators group on {1}".FormatWith(credential.UserName, citrixServer)); PrincipalContext domainContext = new PrincipalContext(ContextType.Domain, credential.Domain); UserPrincipal user = UserPrincipal.FindByIdentity(domainContext, credential.UserName); PrincipalContext citrixContext = new PrincipalContext(ContextType.Machine, citrixServer); GroupPrincipal administrators = GroupPrincipal.FindByIdentity(citrixContext, "Administrators"); ActiveDirectoryController.RemoveUserFromGroup(user, administrators); }
/// <summary> /// Initializes a new instance of the <see cref="MachineReservationHandler"/> class. /// </summary> /// <param name="manifest">The manifest.</param> public CitrixPublishedApplicationHandler(SystemManifest manifest) : base(manifest) { _worker = SystemManifest.Resources.OfType <CitrixWorkerDetail>().First(); _citrixServer = _worker.ServerHostname; _credential = SystemManifest.Resources.Credentials.First(); VirtualResourceEventBus.OnStartMainRun += VirtualResourceEventBus_OnStartMainRun; VirtualResourceEventBus.OnShutdownResource += VirtualResourceEventBus_OnShutdownResource; VirtualResourceEventBus.OnPauseResource += VirtualResourceEventBus_OnPauseResource; VirtualResourceEventBus.OnResumeResource += VirtualResourceEventBus_OnResumeResource; }
/// <summary> /// Pings the worker. /// </summary> /// <param name="credential">The credential.</param> /// <returns></returns> private bool PingWorker(OfficeWorkerCredential credential) { bool result = false; var endpoint = new Uri("http://{0}:{1}/{2}".FormatWith(_citrixServer, credential.Port, WcfService.VirtualResource)); TraceFactory.Logger.Debug("Pinging {0}".FormatWith(endpoint)); using (var service = VirtualResourceManagementConnection.Create(_citrixServer, credential.Port)) { if (service.Channel.Ping()) { TraceFactory.Logger.Debug("Ping succeeded"); result = true; } } return(result); }
/// <summary> /// Creates the AdminWorker resources. /// </summary> public override void Start() { ChangeMachineStatusMessage("Starting Admin Workers"); OfficeWorkerCredential credential = SystemManifest.Resources.OfType <AdminWorkerDetail>().First().UserCredentials.First(); ConfigureLocalUserGroups(credential); ChangeResourceState(credential.ResourceInstanceId, RuntimeState.Starting); try { StartUserProcess(credential, Directory.GetCurrentDirectory()); } catch { ChangeMachineStatusMessage("Error starting worker {0}".FormatWith(credential.UserName)); ChangeResourceState(credential.ResourceInstanceId, RuntimeState.Error); } }
internal static void StartPublishedApp(OfficeWorkerCredential credential, string citrixServer, string publishedApp) { Environment.SpecialFolder folder = (Environment.Is64BitOperatingSystem) ? Environment.SpecialFolder.ProgramFilesX86 : Environment.SpecialFolder.ProgramFiles; string resourcePath = Path.Combine ( Environment.GetFolderPath(folder), Resources.WFICA32Path ); credential.WorkingDirectory = Directory.GetCurrentDirectory(); TraceFactory.Logger.Debug("Starting published app {0}".FormatWith(publishedApp)); string icaFile = CitrixSessionManager.CreateIcaFile(credential, citrixServer, publishedApp); CitrixSessionManager.StartProcess(credential, resourcePath, icaFile, TimeSpan.FromSeconds(10)); }
/// <summary> /// Initializes a new instance of the <see cref="CitrixWorkerHandler" /> class. /// </summary> /// <param name="manifest">The manifest.</param> public CitrixWorkerHandler(SystemManifest manifest) : base(manifest) { if (manifest == null) { throw new ArgumentNullException("manifest"); } _userProfile = Environment.GetEnvironmentVariable("USERPROFILE"); _credential = SystemManifest.Resources.Credentials.First(); _credential.WorkingDirectory = Directory.GetCurrentDirectory(); _worker = SystemManifest.Resources.OfType <CitrixWorkerDetail>().First(); _citrixServer = _worker.ServerHostname; _randomizeStartupDelay = _worker.RandomizeStartupDelay; _minStartupDelay = TimeSpan.FromSeconds(_worker.MinStartupDelay); _maxStartupDelay = TimeSpan.FromSeconds(_worker.MaxStartupDelay); }
internal static void ConfigureLocalUserGroups(OfficeWorkerCredential credential, string targetHostName) { if (credential == null) { throw new ArgumentNullException("credential"); } // This will attempt to put the user in the Admin group on the target host // By default the target host is the Environment.MachineName, but for Citrix // as an example, it is the Citrix server. TraceFactory.Logger.Debug("Adding {0} to {1}".FormatWith(credential.UserName, targetHostName)); PrincipalContext domainContext = new PrincipalContext(ContextType.Domain, credential.Domain); UserPrincipal user = UserPrincipal.FindByIdentity(domainContext, credential.UserName); PrincipalContext citrixContext = new PrincipalContext(ContextType.Machine, targetHostName); GroupPrincipal administrators = GroupPrincipal.FindByIdentity(citrixContext, "Administrators"); ActiveDirectoryController.AddUserToGroup(user, administrators); }
/// <summary> /// Starts the defined Virtual Resource process for the defined credential. /// </summary> /// <param name="credential">The user credential.</param> /// <param name="currentDirectory">The current directory.</param> protected virtual void StartUserProcess(OfficeWorkerCredential credential, string currentDirectory) { if (credential == null) { throw new ArgumentNullException("credential"); } TraceFactory.Logger.Debug("Starting User Process {0} on port {1}".FormatWith(credential.UserName, credential.Port)); string exeFile = Properties.Resources.OfficeWorkerApplicationFileName; TraceFactory.Logger.Debug(exeFile); var officeWorkerExe = Path.Combine(Path.GetDirectoryName(currentDirectory), exeFile); var commandLine = "{0} {1}".FormatWith ( Environment.MachineName, credential.ResourceInstanceId ); var bootStrapperExePath = Path.Combine(currentDirectory, "OfficeWorkerBootStrapper.exe"); if (File.Exists(bootStrapperExePath)) { commandLine = $"{officeWorkerExe} {Environment.MachineName} {credential.ResourceInstanceId}"; officeWorkerExe = bootStrapperExePath; } TraceFactory.Logger.Debug("Executing {0} {1}".FormatWith(officeWorkerExe, commandLine)); NetworkCredential netCredential = new NetworkCredential(credential.UserName, credential.Password, credential.Domain); ProcessUtil.Launch(officeWorkerExe, commandLine, currentDirectory, netCredential); Thread.Sleep(TimeSpan.FromSeconds(5)); TraceFactory.Logger.Debug("Start User Process Complete".FormatWith(credential.UserName, credential.Port)); }
/// <summary> /// Configures the local user groups. /// </summary> /// <param name="credential">The credential.</param> /// <param name="targetHostName">Name of the target host.</param> protected static void ConfigureLocalUserGroups(OfficeWorkerCredential credential, string targetHostName) { if (credential == null) { throw new ArgumentNullException("credential"); } // This will attempt to put the user in the Admin group on the target host // By default the target host is the Environment.MachineName, but for Citrix // as an example, it is the Citrix server. TraceFactory.Logger.Debug($"User: {credential.UserName}. Domain: {credential.Domain}. MachineName: {targetHostName}."); PrincipalContext domainContext = new PrincipalContext(ContextType.Domain, credential.Domain); UserPrincipal user = UserPrincipal.FindByIdentity(domainContext, credential.UserName); TraceFactory.Logger.Debug($"Found Domain UserPrincipal: {user.Name}"); PrincipalContext machineContext = new PrincipalContext(ContextType.Machine, targetHostName); GroupPrincipal administrators = GroupPrincipal.FindByIdentity(machineContext, "Administrators"); TraceFactory.Logger.Debug($"Found machine GroupPrincipal: {administrators.Name}"); try { ActiveDirectoryController.AddUserToGroup(user, administrators); } catch (System.Runtime.InteropServices.COMException ex) { // The group membership check failed, most likely because the current executing user does not // have permissions to view all the members in the group. This condition produces the follwing error: // System.Runtime.InteropServices.COMException (0x80070035): The network path was not found. TraceFactory.Logger.Debug($"Unable to iterate {administrators.Name} membership. ({ex.GetType().FullName}. {ex.Message.Trim()})"); TraceFactory.Logger.Debug("Attempting add via LDAP."); //Try adding using LDAP ActiveDirectoryController.AddUserToGroupLdap(credential.Domain, credential.UserName, "Administrators"); } }
/// <summary> /// Configures the local user groups. /// </summary> /// <param name="credential">The credential.</param> protected static void ConfigureLocalUserGroups(OfficeWorkerCredential credential) { ConfigureLocalUserGroups(credential, Environment.MachineName); }
internal static void CleanupUserProfile(OfficeWorkerCredential credential) { try { //remove the credential from the administrator group var userPath = GetProfilePath(credential.UserName); TraceFactory.Logger.Debug("Path: {0}".FormatWith(userPath)); RemoveUserFromGroup(credential); if (string.IsNullOrEmpty(userPath)) { return; } DeleteUserRegistry(credential.UserName); if (userPath.Contains("TEMP")) { // If the path contains TEMP, then it's a temporary profile and it will be // deleted automatically on its own. Still go ahead and remove the registry // entry for this user's profile. TraceFactory.Logger.Debug("Temp profile {0}".FormatWith(userPath)); } else { // If the real user directory exists, then delete the directory and then // remove any entry in the registry for this user as well. This will // clean up all profile related information. if (Directory.Exists(userPath)) { TraceFactory.Logger.Debug("Deleting {0}".FormatWith(userPath)); NetworkCredential domainAdminNetworkCredential = new NetworkCredential(GlobalSettings.Items[Setting.DomainAdminUserName], GlobalSettings.Items[Setting.DomainAdminPassword], GlobalSettings.Items[Setting.Domain]); FileSystem.DeleteDirectory(userPath, domainAdminNetworkCredential); //sometimes the files are deleted but the folder structure remains, doing the same thing again works if (Directory.Exists(userPath)) { FileSystem.DeleteDirectory(userPath, domainAdminNetworkCredential); } } else { TraceFactory.Logger.Debug("Path doesn't exist"); } } } catch (IOException ex) { TraceFactory.Logger.Error("IO error", ex); } catch (ObjectDisposedException ex) { TraceFactory.Logger.Error("Object disposed error", ex); } catch (SecurityException ex) { TraceFactory.Logger.Error("Security error", ex); } catch (UnauthorizedAccessException ex) { TraceFactory.Logger.Error("Autorization error", ex); } catch (ArgumentException ex) { TraceFactory.Logger.Error("Arg error", ex); } }
/// <summary> /// Configures User Groups in Activity Directory for each user count.. /// </summary> /// <param name="credential">The credential.</param> /// <param name="addToGroups">Whether to add the user to the AD groups specified in the manifest.</param> protected void ConfigureUserGroups(OfficeWorkerCredential credential, bool addToGroups = true) { if (credential == null) { throw new ArgumentNullException("credential"); } string userName = credential.UserName; // Check to be sure there are user groups to configure string securityGroupXml = SystemManifest.Resources.GetByUsername(userName).SecurityGroups; if (string.IsNullOrEmpty(securityGroupXml)) { // There are no active directory groups to process, so return return; } // Get the groups to be processed and the appropriate logging label Collection <ActiveDirectoryGroup> groups = null; string label = string.Empty; if (addToGroups) { groups = LegacySerializer.DeserializeDataContract <Collection <ActiveDirectoryGroup> >(securityGroupXml); label = "Adding"; } else { groups = new Collection <ActiveDirectoryGroup>(); label = "Removing"; } PrincipalContext context = new PrincipalContext(ContextType.Domain); // Compare what the list of groups are to the master list from Active Directory // for every entry found in active directory add it to the list to be processed. // If there is a group listed to be assigned but it doesn't exist anymore in active // directory, log that error. var groupsToAssign = new List <GroupPrincipal>(); if (addToGroups) { foreach (var group in groups) { GroupPrincipal groupPrincipal = GroupPrincipal.FindByIdentity(context, group.Name); if (groupPrincipal != null) { TraceFactory.Logger.Debug("Group {0} will be assigned to {1}".FormatWith(groupPrincipal.Name, credential.UserName)); groupsToAssign.Add(groupPrincipal); } else { TraceFactory.Logger.Error("The group {0} does not exist in the Active Directory server".FormatWith(group.Name)); } } } // Find any groups the user is a member of that must be removed. Ignore Domain Users, since that group cannot be unjoined. UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(context, userName); var existingUserGroups = userPrincipal.GetAuthorizationGroups().OfType <GroupPrincipal>(); var groupsToRemove = existingUserGroups.Except(groupsToAssign).Where(n => n.Name != "Domain Users"); Action action = () => { ActiveDirectoryController.RemoveUserFromGroups(userPrincipal, groupsToRemove); ActiveDirectoryController.AddUserToGroups(userPrincipal, groupsToAssign); }; try { Retry.WhileThrowing(action, 10, TimeSpan.FromSeconds(5), new List <Type> { typeof(DirectoryServicesCOMException) }); } catch (UnauthorizedAccessException) { TraceFactory.Logger.Debug("User {0} is not authorized to assign group membership. {1} will not be assigned." .FormatWith(Environment.UserName, credential.UserName)); } }
private bool CheckSessionStarted(OfficeWorkerCredential credential, string resourcePath) { bool sessionStarted = false; string appId = string.Empty; // The Citrix Office Worker can run on a Citrix server in two different ways, one as a published // app and the other under a desktop session. This block of code defines how the ICA file // should be constructed in order to run the session in one of the two options. It is based // on the value of the RunMode which is chosen by the user at runtime. switch (_worker.WorkerRunMode) { case CitrixWorkerRunMode.Desktop: string key = "{0}-CitrixWorkerDesktop".FormatWith(_citrixServer); appId = GlobalSettings.Items[key]; if (string.IsNullOrEmpty(appId)) { throw new InvalidOperationException("The CitrixWorkerDesktop System Setting value is missing."); } break; case CitrixWorkerRunMode.PublishedApp: appId = "{0}-OWC".FormatWith(_citrixServer); break; } // Start the worker process on the remote Citrix server by running the ICA client // as administrator, and the ICA config file contains the credentials for the the // actual Office Worker string icaFile = CitrixSessionManager.CreateIcaFile(credential, _citrixServer, appId); CitrixSessionManager.StartProcess(credential, resourcePath, icaFile, TimeSpan.FromSeconds(10)); // The Citrix server will display a Citrix license warning anytime a user is not admin // and is running a client process. So delay here about 10 seconds to let this dialog // display and eventually go away. TraceFactory.Logger.Info("Sleep 20 seconds to wait on Citrix to startup"); Thread.Sleep(TimeSpan.FromSeconds(20)); try { Retry.WhileThrowing ( () => sessionStarted = PingWorker(credential), 10, TimeSpan.FromSeconds(10), new List <Type>() { typeof(FaultException), typeof(EndpointNotFoundException), typeof(SocketException) } ); } catch (FaultException ex) { TraceFactory.Logger.Debug("Ping worker failed (1): {0}".FormatWith(ex.Message)); } catch (EndpointNotFoundException ex) { TraceFactory.Logger.Debug("Ping worker failed (2): {0}".FormatWith(ex.Message)); } catch (SocketException ex) { TraceFactory.Logger.Debug("Ping worker failed (3): {0}".FormatWith(ex.Message)); } catch (Exception ex) { TraceFactory.Logger.Debug("Ping worker failed (4): {0}".FormatWith(ex.Message)); } finally { TraceFactory.Logger.Debug("Session Started: {0}".FormatWith(sessionStarted)); } return(sessionStarted); }
/// <summary> /// Starts the defined process. /// </summary> /// <param name="credential">The credential.</param> /// <param name="fileName">Name of the file.</param> /// <param name="arguments">The arguments.</param> /// <param name="timeout">The timeout.</param> /// <param name="reverseWait">if set to <c>true</c> [reverse wait].</param> /// <returns></returns> internal static bool StartProcess ( OfficeWorkerCredential credential, string fileName, string arguments, TimeSpan timeout, bool reverseWait = false ) { bool completed = false; try { using (Process p = new Process()) { p.StartInfo.FileName = fileName; p.StartInfo.Arguments = arguments; p.StartInfo.LoadUserProfile = true; p.StartInfo.CreateNoWindow = false; p.StartInfo.UseShellExecute = false; p.StartInfo.WindowStyle = ProcessWindowStyle.Normal; p.StartInfo.RedirectStandardOutput = true; if (credential != null) { TraceFactory.Logger.Debug("Using credential {0}".FormatWith(credential)); // Convert to NetworkCredential to make use of SecureString for password NetworkCredential networkCredential = new NetworkCredential(credential.UserName, credential.Password, credential.Domain); p.StartInfo.UserName = networkCredential.UserName; p.StartInfo.Domain = networkCredential.Domain; p.StartInfo.Password = networkCredential.SecurePassword; } TraceFactory.Logger.Debug("{0} {1}".FormatWith(fileName, arguments)); p.Start(); if (!reverseWait) { // Read standard out on processes that should run to completion StreamReader reader = p.StandardOutput; TraceFactory.Logger.Debug("STDOUT: " + reader.ReadLine()); if (!p.WaitForExit((int)timeout.TotalMilliseconds)) { TraceFactory.Logger.Debug("Process failed to start, Exit Code: ".FormatWith(p.ExitCode)); } else { completed = true; } } else { TraceFactory.Logger.Debug("Reverse wait"); // If we come back immediately because we didn't reach the timeout, // then something went wrong. The process should not terminate, so // we should reach the timeout, which would cause WaitForExit to return // false. If it returns true, then the process exited for some reason. if (p.WaitForExit((int)timeout.TotalMilliseconds)) { TraceFactory.Logger.Debug("Process failed to start, Exit Code: ".FormatWith(p.ExitCode)); } else { completed = true; } } } } finally { } return(completed); }
/// <summary> /// Wrapper used to clean up the specified user profile path. /// </summary> /// <param name="credential"></param> public void Cleanup(OfficeWorkerCredential credential) { VirtualResourceUserProfile.Cleanup(credential); }