private void SetupListener() { try { this.stopped = false; LdapDirectoryIdentifier directory = new LdapDirectoryIdentifier(this.HostName); NetworkCredential creds = this.GetCredentialPackage(); if (creds != null) { this.Log($"Connecting to {this.HostName} as {this.Username}"); this.connection = new LdapConnection(directory, creds); } else { this.Log($"Connecting to {this.HostName} as {Thread.CurrentPrincipal.Identity.Name}"); this.connection = new LdapConnection(directory); } List <string> attributesToGet = new List <string>() { ActiveDirectoryChangeTrigger.ObjectClassAttribute }; attributesToGet.AddRange(ActiveDirectoryChangeTrigger.TimeStampAttributesToIgnore); SearchRequest r = new SearchRequest( this.BaseDN, "(objectClass=*)", SearchScope.Subtree, attributesToGet.ToArray() ); r.Controls.Add(new DirectoryNotificationControl()); this.request = this.connection.BeginSendRequest( r, TimeSpan.FromDays(100), PartialResultProcessing.ReturnPartialResultsAndNotifyCallback, this.Notify, r); this.Log($"Listening for changes from {this.HostName}"); } catch (Exception ex) { this.LogError("Could not start the listener", ex); if (MessageSender.CanSendMail()) { string messageContent = MessageBuilder.GetMessageBody(this.ManagementAgentName, this.Type, this.Description, DateTime.Now, true, ex); MessageSender.SendMessage($"{this.ManagementAgentName}: {this.Type} trigger error", messageContent); } throw; } }
private void SetupListener() { try { this.stopped = false; LdapDirectoryIdentifier directory = new LdapDirectoryIdentifier(this.HostName); if (this.HasCredentials) { this.connection = new LdapConnection(directory, this.GetCredentialPackage()); } else { this.connection = new LdapConnection(directory); } SearchRequest r = new SearchRequest( this.BaseDN, "(objectClass=*)", SearchScope.Subtree, ActiveDirectoryChangeTrigger.ObjectClassAttribute, ActiveDirectoryChangeTrigger.LastLogonAttributeName, ActiveDirectoryChangeTrigger.LastLogonTimeStampAttributeName, ActiveDirectoryChangeTrigger.BadPasswordAttribute); r.Controls.Add(new DirectoryNotificationControl()); this.request = this.connection.BeginSendRequest( r, TimeSpan.FromDays(100), PartialResultProcessing.ReturnPartialResultsAndNotifyCallback, this.Notify, r); } catch (Exception ex) { this.LogError("Could not start the listener", ex); if (MessageSender.CanSendMail()) { string messageContent = MessageBuilder.GetMessageBody(this.ManagementAgentName, this.Type, this.Description, DateTime.Now, true, ex); MessageSender.SendMessage($"{this.ManagementAgentName}: {this.Type} trigger error", messageContent); } throw; } }
private void CheckTimer_Elapsed(object sender, ElapsedEventArgs e) { try { ResourceManagementClient c = new ResourceManagementClient(this.HostName); string xpath; if (this.lastCheckDateTime == null) { xpath = "/Request"; this.Trace("No watermark available. Querying for latest request history item"); } else { xpath = string.Format("/Request[msidmCompletedTime > '{0}']", this.lastCheckDateTime.Value.ToResourceManagementServiceDateFormat(false)); this.Trace($"Searching for changes since {this.lastCheckDateTime.Value.ToResourceManagementServiceDateFormat(false)}"); } ISearchResultCollection r = c.GetResources(xpath, 1, new[] { "msidmCompletedTime" }, "msidmCompletedTime", false); this.Trace($"Found {r.Count} change{r.Count.Pluralize()}"); if (r.Count <= 0) { return; } this.lastCheckDateTime = r.First().Attributes["msidmCompletedTime"].DateTimeValue; this.Fire(MARunProfileType.DeltaImport, "default"); } catch (Exception ex) { this.LogError("Change detection failed", ex); if (MessageSender.CanSendMail()) { string messageContent = MessageBuilder.GetMessageBody(this.ManagementAgentName, this.Type, this.Description, DateTime.Now, false, ex); MessageSender.SendMessage($"{this.ManagementAgentName}: {this.Type} trigger error", messageContent); } } }
private void Run() { try { Thread.CurrentThread.SetThreadName($"{this.DisplayName} on {this.ManagementAgentName}"); this.powershell = PowerShell.Create(); this.powershell.AddScript(System.IO.File.ReadAllText(this.ScriptPath)); this.powershell.Invoke(); if (this.powershell.Runspace.SessionStateProxy.InvokeCommand.GetCommand("Get-RunProfileToExecute", CommandTypes.All) == null) { this.LogError($"The file '{this.ScriptPath}' did not contain a function called Get-RunProfileToExecute and will be ignored"); return; } while (!this.cancellationToken.Token.IsCancellationRequested) { this.cancellationToken.Token.ThrowIfCancellationRequested(); this.powershell.ResetState(); this.powershell.AddCommand("Get-RunProfileToExecute"); Collection <PSObject> results; try { results = this.powershell.Invoke(); this.cancellationToken.Token.ThrowIfCancellationRequested(); this.powershell.ThrowOnPipelineError(); } catch (OperationCanceledException) { throw; } catch (Exception ex) { bool shouldTerminate = this.ExceptionBehaviour == ExecutionErrorBehaviour.Terminate; this.LogError($"The PowerShell execution trigger '{this.DisplayName}' encountered an error", ex); if (MessageSender.CanSendMail()) { string messageContent = MessageBuilder.GetMessageBody(this.ManagementAgentName, this.Type, this.Description, DateTime.Now, shouldTerminate, ex); MessageSender.SendMessage($"{this.ManagementAgentName}: {this.Type} trigger error", messageContent); } if (shouldTerminate) { this.Log("The PowerShell trigger has been terminated as specified by config"); break; } else { if (!this.cancellationToken.IsCancellationRequested) { this.cancellationToken.Token.WaitHandle.WaitOne(this.Interval); } continue; } } foreach (PSObject result in results) { string runProfileName = result.BaseObject as string; if (runProfileName != null) { this.Fire(runProfileName); continue; } ExecutionParameters p = result.BaseObject as ExecutionParameters; if (p == null) { continue; } this.Fire(p); } this.cancellationToken.Token.ThrowIfCancellationRequested(); this.cancellationToken.Token.WaitHandle.WaitOne(this.Interval); } } catch (OperationCanceledException) { } catch (Exception ex) { this.LogError("The PowerShell execution trigger encountered an error and has been terminated", ex); if (MessageSender.CanSendMail()) { string messageContent = MessageBuilder.GetMessageBody(this.ManagementAgentName, this.Type, this.Description, DateTime.Now, true, ex); MessageSender.SendMessage($"{this.ManagementAgentName}: {this.Type} trigger error", messageContent); } } }
private void Run() { try { Thread.CurrentThread.SetThreadName($"{this.DisplayName} on {this.ManagementAgentName}"); this.powershell = PowerShell.Create(); this.powershell.AddScript(System.IO.File.ReadAllText(this.ScriptPath)); this.powershell.Invoke(); CommandInfo c = this.powershell.Runspace.SessionStateProxy.InvokeCommand.GetCommand("Get-RunProfileToExecute", CommandTypes.All); if (c == null) { this.LogError($"The file '{this.ScriptPath}' did not contain a function called Get-RunProfileToExecute and will be ignored"); return; } bool cmdletRequiresCredentials = c.Parameters.ContainsKey("credentials"); PSCredential creds = this.GetCredentialPackage(); if (creds != null && !cmdletRequiresCredentials) { this.LogError("Credentials were provided for the PowerShell script, but the Get-RunProfileToExecute function did not contain a 'credentials' parameter. See the wiki topic (https://github.com/lithnet/miis-autosync/wiki/Powershell-script-trigger) for more information"); } while (!this.cancellationToken.Token.IsCancellationRequested) { this.cancellationToken.Token.ThrowIfCancellationRequested(); this.powershell.ResetState(); if (cmdletRequiresCredentials) { this.powershell.AddCommand("Get-RunProfileToExecute").AddParameter("credentials", creds); } else { this.powershell.AddCommand("Get-RunProfileToExecute"); } Collection <PSObject> results; try { results = this.powershell.Invoke(); this.cancellationToken.Token.ThrowIfCancellationRequested(); this.powershell.ThrowOnPipelineError(); } catch (OperationCanceledException) { throw; } catch (Exception ex) { bool shouldTerminate = this.ExceptionBehaviour == ExecutionErrorBehaviour.Terminate; this.LogError($"The PowerShell execution trigger '{this.DisplayName}' encountered an error", ex); if (MessageSender.CanSendMail()) { string messageContent = MessageBuilder.GetMessageBody(this.ManagementAgentName, this.Type, this.Description, DateTime.Now, shouldTerminate, ex); MessageSender.SendMessage($"{this.ManagementAgentName}: {this.Type} trigger error", messageContent); } if (shouldTerminate) { this.Log("The PowerShell trigger has been terminated as specified by config"); break; } else { if (!this.cancellationToken.IsCancellationRequested) { this.cancellationToken.Token.WaitHandle.WaitOne(this.Interval); } continue; } } foreach (PSObject result in results) { string runProfileName = result.BaseObject as string; if (runProfileName != null) { this.Fire(runProfileName); continue; } ExecutionParameters p = result.BaseObject as ExecutionParameters; if (p == null) { continue; } this.Fire(p); } this.cancellationToken.Token.ThrowIfCancellationRequested(); this.cancellationToken.Token.WaitHandle.WaitOne(this.Interval); } } catch (OperationCanceledException) { } catch (Exception ex) { this.LogError("The PowerShell execution trigger encountered an error and has been terminated", ex); if (MessageSender.CanSendMail()) { string messageContent = MessageBuilder.GetMessageBody(this.ManagementAgentName, this.Type, this.Description, DateTime.Now, true, ex); MessageSender.SendMessage($"{this.ManagementAgentName}: {this.Type} trigger error", messageContent); } } }
private void Notify(IAsyncResult result) { lock (this.lockObject) { try { if (this.stopped) { this.connection?.EndSendRequest(result); return; } PartialResultsCollection resultsCollection = this.connection?.GetPartialResults(result); if (resultsCollection == null) { this.Trace("Results collection was empty"); return; } if (DateTime.Now < this.nextTriggerAfter) { //this.Trace("Discarding change because next trigger time has not been reached"); return; } DateTime lastLogonOldestDate = DateTime.UtcNow.Subtract(this.LastLogonTimestampOffset); foreach (SearchResultEntry r in resultsCollection.OfType <SearchResultEntry>()) { if (r.Attributes == null || !r.Attributes.Contains(ActiveDirectoryChangeTrigger.ObjectClassAttribute)) { this.Trace($"Skipping entry {r.DistinguishedName} because the object class list was empty"); continue; } IList <string> objectClasses = r.Attributes[ActiveDirectoryChangeTrigger.ObjectClassAttribute].GetValues(typeof(string)).OfType <string>().ToList(); if (!this.ObjectClasses.Intersect(objectClasses, StringComparer.OrdinalIgnoreCase).Any()) { continue; } if (objectClasses.Contains("computer", StringComparer.OrdinalIgnoreCase) && !this.ObjectClasses.Contains("computer", StringComparer.OrdinalIgnoreCase)) { continue; } bool dateTooSoon = false; foreach (string timestampAttribute in ActiveDirectoryChangeTrigger.TimeStampAttributesToIgnore) { if (r.Attributes.Contains(timestampAttribute)) { string ts = r.Attributes[timestampAttribute][0] as string; DateTime date1 = DateTime.FromFileTimeUtc(Convert.ToInt64(ts)); if (date1 > lastLogonOldestDate) { dateTooSoon = true; break; } } } if (dateTooSoon) { continue; } this.Log($"Change detected on {r.DistinguishedName}"); this.Fire(); } } catch (LdapException ex) { if (ex.ErrorCode == 85) { this.SetupListener(); } else { this.LogError("The AD change listener encountered an unexpected error", ex); if (MessageSender.CanSendMail()) { string messageContent = MessageBuilder.GetMessageBody(this.ManagementAgentName, this.Type, this.Description, DateTime.Now, false, ex); MessageSender.SendMessage($"{this.ManagementAgentName}: {this.Type} trigger error", messageContent); Thread.Sleep(1000); } } } catch (Exception ex) { this.LogError("The AD change listener encountered an unexpected error", ex); if (MessageSender.CanSendMail()) { string messageContent = MessageBuilder.GetMessageBody(this.ManagementAgentName, this.Type, this.Description, DateTime.Now, false, ex); MessageSender.SendMessage($"{this.ManagementAgentName}: {this.Type} trigger error", messageContent); Thread.Sleep(1000); } } } }