private List <SecurityDescriptorTarget> ConvertToTargets(OUPrincipalMapping entry)
        {
            List <SecurityDescriptorTarget> targets = new List <SecurityDescriptorTarget>();

            this.PopulateTargets(entry, targets);

            return(targets);
        }
        protected ImportResults PerformComputerDiscovery(IComputerPrincipalProvider provider)
        {
            OUPrincipalMapping ou = new OUPrincipalMapping($"LDAP://{settings.ImportOU}", settings.ImportOU);

            ImportResults results = new ImportResults
            {
                DiscoveryErrors = new List <DiscoveryError>(),
            };

            principalCache = new ConcurrentDictionary <SecurityIdentifier, ISecurityPrincipal>();

            this.PerformComputerDiscovery(ou, provider, results.DiscoveryErrors);

            principalCache.Clear();

            results.Targets = this.ConvertToTargets(ou);

            return(results);
        }
        private SecurityDescriptorTarget ConvertToTarget(OUPrincipalMapping entry, HashSet <SecurityIdentifier> admins)
        {
            this.logger.LogTrace("Creating new target for OU {ou} with the following principals\r\n{admins}", entry.AdsPath, string.Join(", ", admins));

            SecurityDescriptorTarget target = new SecurityDescriptorTarget()
            {
                AuthorizationMode = AuthorizationMode.SecurityDescriptor,
                Description       = settings.RuleDescription?.Replace("{targetName}", entry.OUName, StringComparison.OrdinalIgnoreCase),
                Target            = entry.OUName,
                Type          = TargetType.Container,
                Id            = Guid.NewGuid().ToString(),
                Notifications = settings.Notifications,
                Jit           = new SecurityDescriptorTargetJitDetails()
                {
                    AuthorizingGroup = settings.JitAuthorizingGroup,
                    ExpireAfter      = settings.JitExpireAfter
                },
                Laps = new SecurityDescriptorTargetLapsDetails()
                {
                    ExpireAfter = settings.LapsExpireAfter
                }
            };

            AccessMask mask = 0;

            mask |= settings.AllowLaps ? AccessMask.LocalAdminPassword : 0;
            mask |= settings.AllowJit ? AccessMask.Jit : 0;
            mask |= settings.AllowLapsHistory ? AccessMask.LocalAdminPasswordHistory : 0;
            mask |= settings.AllowBitLocker ? AccessMask.BitLocker : 0;

            DiscretionaryAcl acl = new DiscretionaryAcl(false, false, admins.Count);

            foreach (var sid in admins)
            {
                acl.AddAccess(AccessControlType.Allow, sid, (int)mask, InheritanceFlags.None, PropagationFlags.None);
            }

            CommonSecurityDescriptor sd = new CommonSecurityDescriptor(false, false, ControlFlags.DiscretionaryAclPresent, new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null), null, null, acl);

            target.SecurityDescriptor = sd.GetSddlForm(AccessControlSections.All);

            return(target);
        }
        private void PopulateTargets(OUPrincipalMapping entry, List <SecurityDescriptorTarget> targets)
        {
            bool canConsolidate = !(settings.DoNotConsolidate || (settings.DoNotConsolidateOnError && entry.HasDescendantsWithErrors));

            this.logger.LogTrace(@"Processing OU
Path: {ou}
Consolidating: {consolidating}
DoNotConsolidate flag: {DoNotConsolidate}
DoNotConsolidateOnError flag : {DoNotConsolidateOnError}
HasDescendantsWithErrors: {HasDescendantsWithErrors}
ParentHasDescendantsWithErrors: {ParentHasDescendantsWithErrors}
Computers: {ComputerCount} : {Computers}
CommonPrincipalsFromDescendants: {CommonPrincipalsFromDescendantsCount} : {CommonPrincipalsFromDescendants}
PrincipalsUniqueToThisLevel: {PrincipalsUniqueToThisLevelCount} : {PrincipalsUniqueToThisLevel}
",
                                 entry.AdsPath,
                                 canConsolidate,
                                 settings.DoNotConsolidate,
                                 settings.DoNotConsolidateOnError,
                                 entry.HasDescendantsWithErrors,
                                 entry.Parent?.HasDescendantsWithErrors,
                                 entry.Computers.Count,
                                 string.Join(", ", entry.Computers.Select(t => t.PrincipalName)),
                                 entry.CommonPrincipalsFromDescendants.Count,
                                 string.Join(", ", entry.CommonPrincipalsFromDescendants),
                                 entry.PrincipalsUniqueToThisLevel.Count,
                                 string.Join(", ", entry.PrincipalsUniqueToThisLevel)
                                 );

            if (canConsolidate)
            {
                HashSet <SecurityIdentifier> admins;

                if (settings.DoNotConsolidateOnError && (entry.Parent?.HasDescendantsWithErrors ?? false))
                {
                    // The parent OU is in error, so we cannot remove common principals that the parent may have
                    admins = entry.CommonPrincipalsFromDescendants;
                    this.logger.LogTrace("Permissions for the OU {OU} will not be consolidated against the parent OU because the parent OU one or more descendant errors", entry.AdsPath);
                }
                else
                {
                    // Principals that are present on the parent OU are removed from the principal set here
                    admins = entry.PrincipalsUniqueToThisLevel;
                    this.logger.LogTrace("Permissions for the OU {OU} will be consolidated against its parent", entry.AdsPath);
                }

                if (admins.Count > 0)
                {
                    targets.Add(this.ConvertToTarget(entry, admins));
                }
                else
                {
                    this.logger.LogTrace("There were no principals that require a rule being created for {target}", entry.AdsPath);
                }
            }

            foreach (var computer in entry.Computers)
            {
                this.logger.LogTrace(@"Processing computer
Principal: {computer}
Consolidating: {consolidating}
DoNotConsolidate flag: {DoNotConsolidate}
DoNotConsolidateOnError flag : {DoNotConsolidateOnError}
HasError: {HasError}
IsMissing: {IsMissing}
ParentHasErrors: {ParentHasDescendantsWithErrors}
DiscoveryErrors: {DiscoveryErrorCount} : {DiscoveryErrors}
Principals: {PrincipalsCount} : {Principals}
PrincipalsUniqueToThisLevel: {PrincipalsUniqueToThisLevelCount} : {PrincipalsUniqueToThisLevel}
",
                                     computer.PrincipalName,
                                     canConsolidate,
                                     settings.DoNotConsolidate,
                                     settings.DoNotConsolidateOnError,
                                     computer.HasError,
                                     computer.IsMissing,
                                     entry.HasDescendantsWithErrors,
                                     computer.DiscoveryErrors.Count,
                                     string.Join(", ", computer.DiscoveryErrors?.Select(t => t.Message)),
                                     computer.Principals.Count,
                                     string.Join(", ", computer.Principals),
                                     computer.PrincipalsUniqueToThisLevel.Count,
                                     string.Join(", ", computer.PrincipalsUniqueToThisLevel)
                                     );

                if (computer.HasError)
                {
                    this.logger.LogTrace("Skipping permissions for computer {computer} due to discovery errors", computer.PrincipalName);
                    continue;
                }

                HashSet <SecurityIdentifier> admins;

                if (settings.DoNotConsolidate)
                {
                    admins = computer.Principals;
                    this.logger.LogTrace("Permissions for computer {computer} will not be consolidated because consolidation has been disabled", computer.PrincipalName);
                }
                else if (settings.DoNotConsolidateOnError && entry.HasDescendantsWithErrors)
                {
                    admins = computer.Principals;
                    this.logger.LogTrace("Permissions for computer {computer} will not be consolidated because the parent OU has decendant errors", computer.PrincipalName);
                }
                else
                {
                    admins = computer.PrincipalsUniqueToThisLevel;
                    this.logger.LogTrace("Permissions for computer {computer} can be consolidated", computer.PrincipalName);
                }

                if (admins.Count > 0)
                {
                    targets.Add(this.ConvertToTarget(computer, admins));
                }
                else
                {
                    this.logger.LogTrace("There were no principals that require a rule being created for {target}", computer.PrincipalName);
                }
            }

            foreach (var ou in entry.DescendantOUs)
            {
                this.PopulateTargets(ou, targets);
            }
        }
        private void PerformComputerDiscovery(OUPrincipalMapping ou, IComputerPrincipalProvider principalProvider, List <DiscoveryError> discoveryErrors)
        {
            settings.CancellationToken.ThrowIfCancellationRequested();

            foreach (SearchResult computer in this.GetComputersFromOU(ou.AdsPath, false, principalProvider))
            {
                settings.CancellationToken.ThrowIfCancellationRequested();
                string computerName = computer.GetPropertyString("msDS-PrincipalName");
                try
                {
                    this.OnItemProcessStart?.Invoke(this, new ImportProcessingEventArgs(computerName));

                    if (this.ShouldFilterComputer(computer))
                    {
                        this.logger.LogTrace("Filtering computer {computer}", computerName);
                        continue;
                    }

                    this.logger.LogTrace("Found computer {computer} in ou {ou}", computerName, ou.OUName);

                    ComputerPrincipalMapping ce = new ComputerPrincipalMapping(computer, ou);

                    ou.Computers.Add(ce);

                    try
                    {
                        HashSet <SecurityIdentifier> principalsForComputer = new HashSet <SecurityIdentifier>(principalProvider.GetPrincipalsForComputer(computer, settings.FilterLocalAccounts));

                        this.logger.LogTrace("Got {number} principals from computer {computer}", principalsForComputer.Count, computerName);

                        foreach (var principal in principalsForComputer)
                        {
                            settings.CancellationToken.ThrowIfCancellationRequested();

                            if (this.ShouldFilter(principal, out DiscoveryError filterReason))
                            {
                                if (filterReason != null)
                                {
                                    filterReason.Target = computerName;
                                    ce.DiscoveryErrors.Add(filterReason);
                                    this.logger.LogTrace("Filtering principal {principal} with reason: {reason}", principal.ToString(), filterReason);
                                }
                            }
                            else
                            {
                                ce.Principals.Add(principal);
                            }
                        }
                    }
                    catch (OperationCanceledException)
                    {
                        return;
                    }
                    catch (Exception ex)
                    {
                        this.logger.LogTrace(ex, "Failed to get principals from computer {computer}", computerName);
                        ce.HasError  = true;
                        ce.Exception = ex;
                        ce.IsMissing = ex is ObjectNotFoundException;
                        ce.DiscoveryErrors.Add(new DiscoveryError()
                        {
                            Target = computerName, Message = ex.Message, Type = DiscoveryErrorType.Error
                        });
                    }

                    if (ce.DiscoveryErrors.Count > 0)
                    {
                        discoveryErrors.AddRange(ce.DiscoveryErrors);
                    }
                }
                finally
                {
                    this.OnItemProcessFinish?.Invoke(this, new ImportProcessingEventArgs(computerName));
                }
            }

            foreach (var childOU in this.GetOUs(ou.AdsPath, false))
            {
                settings.CancellationToken.ThrowIfCancellationRequested();

                this.logger.LogTrace("Found ou {ou}", childOU.GetPropertyString("distinguishedName"));

                OUPrincipalMapping childou = new OUPrincipalMapping(childOU, ou);

                ou.DescendantOUs.Add(childou);
                this.PerformComputerDiscovery(childou, principalProvider, discoveryErrors);
            }
        }
 internal OUPrincipalMapping(SearchResult result, OUPrincipalMapping parent)
 {
     this.AdsPath = result.Path;
     this.OUName  = result.GetPropertyString("distinguishedName");
     this.Parent  = parent;
 }
示例#7
0
 internal ComputerPrincipalMapping(SearchResult computer, OUPrincipalMapping parent)
 {
     this.Parent   = parent;
     this.computer = computer;
 }