Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds -Credential parameter and Truncate Warning #15

Merged
merged 13 commits into from
Sep 7, 2024
2 changes: 1 addition & 1 deletion docs/en-US/Get-ADTreeGroupMember.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ The `-ShowAll` switch indicates that the cmdlet should display the hierarchy of
### -Depth

Determines the number of nested groups and their members included in the recursion.
By default, only 3 levels of recursion are included.
By default, only 3 levels of recursion are included. `Get-ADTreeGroupMember` emits a warning if the levels exceed this number.

```yaml
Type: Int32
Expand Down
2 changes: 1 addition & 1 deletion docs/en-US/Get-ADTreePrincipalGroupMembership.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ The `-ShowAll` switch indicates that the cmdlet should display the hierarchy of
### -Depth

Determines the number of nested group memberships included in the recursion.
By default, only 3 levels of recursion are included.
By default, only 3 levels of recursion are included. `Get-ADTreePrincipalGroupMembership` emits a warning if the levels exceed this number.

```yaml
Type: Int32
Expand Down
35 changes: 18 additions & 17 deletions src/PSADTree/Commands/GetADTreeGroupMemberCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,35 @@ protected override void ProcessRecord()
{
Dbg.Assert(Identity is not null);
Dbg.Assert(_context is not null);
_truncatedOutput = false;

try
{
using GroupPrincipal? group = GroupPrincipal.FindByIdentity(_context, Identity);
if (group is null)
{
WriteError(ErrorHelper.IdentityNotFound(Identity));
WriteError(Exceptions.IdentityNotFound(Identity));
return;
}

WriteObject(
sendToPipeline: Traverse(
groupPrincipal: group,
source: group.DistinguishedName),
enumerateCollection: true);
TreeObjectBase[] result = Traverse(
groupPrincipal: group,
source: group.DistinguishedName);

DisplayWarningIfTruncatedOutput();
WriteObject(sendToPipeline: result, enumerateCollection: true);
}
catch (Exception e) when (e is PipelineStoppedException or FlowControlException)
catch (Exception _) when (_ is PipelineStoppedException or FlowControlException)
{
throw;
}
catch (MultipleMatchesException e)
catch (MultipleMatchesException exception)
{
WriteError(e.AmbiguousIdentity(Identity));
WriteError(exception.AmbiguousIdentity(Identity));
}
catch (Exception e)
catch (Exception exception)
{
WriteError(e.Unspecified(Identity));
WriteError(exception.Unspecified(Identity));
}
}

Expand Down Expand Up @@ -105,13 +107,13 @@ private TreeObjectBase[] Traverse(
_index.TryAddPrincipals();
current?.Dispose();
}
catch (Exception e) when (e is PipelineStoppedException or FlowControlException)
catch (Exception _) when (_ is PipelineStoppedException or FlowControlException)
{
throw;
}
catch (Exception e)
catch (Exception exception)
{
WriteError(e.EnumerationFailure(current));
WriteError(exception.EnumerationFailure(current));
}
}

Expand Down Expand Up @@ -183,7 +185,7 @@ private TreeObjectBase ProcessPrincipal(

TreeObjectBase AddTreeObject(TreeObjectBase obj)
{
if (Recursive.IsPresent || depth <= Depth)
if (depth <= Depth)
{
_index.AddPrincipal(obj);
}
Expand Down Expand Up @@ -211,7 +213,6 @@ TreeObjectBase HandleGroup(

private void EnumerateMembers(TreeGroup parent, int depth)
{
bool shouldProcess = Recursive.IsPresent || depth <= Depth;
foreach (TreeObjectBase member in parent.Childs)
{
if (member is TreeGroup treeGroup)
Expand All @@ -220,7 +221,7 @@ private void EnumerateMembers(TreeGroup parent, int depth)
continue;
}

if (shouldProcess)
if (depth <= Depth)
{
_index.Add(member.Clone(parent, depth));
}
Expand Down
37 changes: 19 additions & 18 deletions src/PSADTree/Commands/GetADTreePrincipalGroupMembershipCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,32 @@ protected override void ProcessRecord()
{
Dbg.Assert(Identity is not null);
Dbg.Assert(_context is not null);
_truncatedOutput = false;
Principal? principal;
Clear();

try
{
principal = Principal.FindByIdentity(_context, Identity);
}
catch (Exception e) when (e is PipelineStoppedException or FlowControlException)
catch (Exception _) when (_ is PipelineStoppedException or FlowControlException)
{
throw;
}
catch (MultipleMatchesException e)
catch (MultipleMatchesException exception)
{
WriteError(e.AmbiguousIdentity(Identity));
WriteError(exception.AmbiguousIdentity(Identity));
return;
}
catch (Exception e)
catch (Exception exception)
{
WriteError(e.Unspecified(Identity));
WriteError(exception.Unspecified(Identity));
return;
}

if (principal is null)
{
WriteError(ErrorHelper.IdentityNotFound(Identity));
WriteError(Exceptions.IdentityNotFound(Identity));
return;
}

Expand All @@ -69,7 +70,7 @@ protected override void ProcessRecord()

try
{
using PrincipalSearchResult<Principal> search = principal.GetGroups();
using PrincipalSearchResult<Principal> search = principal.GetGroups(_context);
foreach (Principal parent in search.GetSortedEnumerable(_comparer))
{
if (ShouldExclude(parent, _exclusionPatterns))
Expand All @@ -82,22 +83,22 @@ protected override void ProcessRecord()
Push(groupPrincipal, treeGroup);
}
}
catch (Exception e) when (e is PipelineStoppedException or FlowControlException)
catch (Exception _) when (_ is PipelineStoppedException or FlowControlException)
{
throw;
}
catch (Exception e)
catch (Exception exception)
{
WriteError(e.EnumerationFailure(null));
WriteError(exception.EnumerationFailure(null));
}
finally
{
principal?.Dispose();
}

WriteObject(
sendToPipeline: Traverse(source),
enumerateCollection: true);
TreeObjectBase[] result = Traverse(source);
DisplayWarningIfTruncatedOutput();
WriteObject(sendToPipeline: result, enumerateCollection: true);
}

private TreeObjectBase[] Traverse(string source)
Expand Down Expand Up @@ -138,7 +139,7 @@ private TreeObjectBase[] Traverse(string source)
continue;
}

using PrincipalSearchResult<Principal>? search = current?.GetGroups();
using PrincipalSearchResult<Principal>? search = current?.GetGroups(_context);

if (search is not null)
{
Expand All @@ -148,13 +149,13 @@ private TreeObjectBase[] Traverse(string source)
_index.Add(treeGroup);
current?.Dispose();
}
catch (Exception e) when (e is PipelineStoppedException or FlowControlException)
catch (Exception _) when (_ is PipelineStoppedException or FlowControlException)
{
throw;
}
catch (Exception e)
catch (Exception exception)
{
WriteError(e.EnumerationFailure(current));
WriteError(exception.EnumerationFailure(current));
}
}

Expand Down Expand Up @@ -197,7 +198,7 @@ TreeGroup ProcessGroup(GroupPrincipal group)

private void EnumerateMembership(TreeGroup parent, int depth)
{
if (!Recursive.IsPresent && depth > Depth)
if (depth > Depth)
{
return;
}
Expand Down
9 changes: 8 additions & 1 deletion src/PSADTree/ErrorHelper.cs → src/PSADTree/Exceptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace PSADTree;

internal static class ErrorHelper
internal static class Exceptions
{
internal static ErrorRecord IdentityNotFound(string? identity) =>
new(
Expand All @@ -13,6 +13,13 @@ internal static ErrorRecord IdentityNotFound(string? identity) =>
ErrorCategory.ObjectNotFound,
identity);

internal static ErrorRecord CredentialRequiresServer() =>
new(
new ArgumentException("Server parameter is required when Credential parameter is used."),
"CredentialRequiresServer",
ErrorCategory.InvalidOperation,
null);

internal static ErrorRecord AmbiguousIdentity(this Exception exception, string? identity) =>
new(exception, "AmbiguousIdentity", ErrorCategory.InvalidResult, identity);

Expand Down
43 changes: 36 additions & 7 deletions src/PSADTree/PSADTreeCmdletBase.cs
santisq marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public abstract class PSADTreeCmdletBase : PSCmdlet, IDisposable

private bool _disposed;

protected bool _truncatedOutput;

protected readonly Stack<(GroupPrincipal? group, TreeGroup treeGroup)> _stack = new();

internal readonly TreeCache _cache = new();
Expand All @@ -30,7 +32,6 @@ public abstract class PSADTreeCmdletBase : PSCmdlet, IDisposable
| WildcardOptions.CultureInvariant
| WildcardOptions.IgnoreCase;


[Parameter(
Position = 0,
Mandatory = true,
Expand All @@ -40,7 +41,11 @@ public abstract class PSADTreeCmdletBase : PSCmdlet, IDisposable
public string? Identity { get; set; }

[Parameter]
public string? Server { get; set; }
public string Server { get; set; } = Environment.UserDomainName;

[Parameter]
[Credential]
public PSCredential? Credential { get; set; }

[Parameter(ParameterSetName = DepthParameterSet)]
[ValidateRange(0, int.MaxValue)]
Expand All @@ -60,20 +65,29 @@ protected override void BeginProcessing()
{
try
{
if (Recursive.IsPresent)
{
Depth = int.MaxValue;
}

if (Exclude is not null)
{
_exclusionPatterns = Exclude
.Select(e => new WildcardPattern(e, _wpoptions))
.ToArray();
}

if (Server is null)
if (Credential is null)
{
_context = new PrincipalContext(ContextType.Domain);
_context = new PrincipalContext(ContextType.Domain, Server);
return;
}

_context = new PrincipalContext(ContextType.Domain, Server);
_context = new PrincipalContext(
ContextType.Domain,
Server,
Credential.UserName,
Credential.GetNetworkCredential().Password);
}
catch (Exception exception)
{
Expand All @@ -83,9 +97,24 @@ protected override void BeginProcessing()

protected void Push(GroupPrincipal? groupPrincipal, TreeGroup treeGroup)
{
if (Recursive.IsPresent || treeGroup.Depth <= Depth)
if (treeGroup.Depth > Depth)
{
return;
}

if (treeGroup.Depth == Depth)
{
_truncatedOutput = true;
}

_stack.Push((groupPrincipal, treeGroup));
}

protected void DisplayWarningIfTruncatedOutput()
{
if (_truncatedOutput)
{
_stack.Push((groupPrincipal, treeGroup));
WriteWarning($"Result is truncated as enumeration has exceeded the set depth of {Depth}.");
}
}

Expand Down