Badgerati / Pode

Pode is a Cross-Platform PowerShell web framework for creating REST APIs, Web Sites, and TCP/SMTP servers
https://badgerati.github.io/Pode
MIT License
830 stars 92 forks source link

Get-Acl returns empty object in Pode Runspace (only on PS7) #1370

Closed RobinBeismann closed 1 month ago

RobinBeismann commented 1 month ago

Question

I'm trying to build a frontend for AD Group Management and for that I want to parse the AD ACLs on a schedule. I've already done this outside Pode and it works fine. However in Pode (on PS7), I do get an empty ACL object for whatever I try to query. Interesting enough, if I run the Get-Acl in PS7 outside Pode, it works fine.

Reproduce

Outside Pode:

image

Inside Pode:

Test Code: image Result: image

Additional information

I found this issue which sounds related, but even loading it doesn't solve it: https://github.com/PowerShell/PowerShell/issues/18896 I tried calling the DirectoryServices Class to use its' objectSecurity property, but that is also empty in Pode while it works outside: $DSObject = New-Object System.DirectoryServices.DirectoryEntry ("LDAP://$($ADGroup.DistinguishedName)")

Any idea what's going out there?

mdaneri commented 1 month ago

This looks like a PS7 bug when run inside a runspace

You can do this as workaround and I suggest to open a bug to Powershell

Add-PodeSchedule -Name 'ACLGroups' -Cron '@hourly' -OnStart -ScriptBlock {
    # Define the C# code
    $csCode = @"
    using System;
    using System.IO;
    using System.Security.AccessControl;
    using System.Security.Principal;
    using System.Collections.Generic;

    public class AclHelper
    {
        public static string GetAcl(string path)
        {
            try
            {
                FileSystemSecurity security = null;

                if (File.Exists(path))
                {
                    FileInfo fileInfo = new FileInfo(path);
                    security = fileInfo.GetAccessControl();
                }
                else if (Directory.Exists(path))
                {
                    DirectoryInfo directoryInfo = new DirectoryInfo(path);
                    security = directoryInfo.GetAccessControl();
                }
                else
                {
                    return "Path not found.";
                }

                var owner = security.GetOwner(typeof(NTAccount)).ToString();
                var rules = security.GetAccessRules(true, true, typeof(NTAccount));

                List<string> aclDetails = new List<string>();
                aclDetails.Add("Owner: " + owner);

                foreach (FileSystemAccessRule rule in rules)
                {
                    aclDetails.Add($"{rule.IdentityReference.Value} {rule.AccessControlType} {rule.FileSystemRights}");
                }

                return string.Join("\n", aclDetails);
            }
            catch (Exception ex)
            {
                return "Error: " + ex.Message;
            }
        }
    }
    "@

    # Add the C# code to the PowerShell session
    Add-Type -TypeDefinition $csCode -Language CSharp 

    # Get the ACL information
    $aclInfo = [AclHelper]::GetAcl($path)
        Write-PodeHost -Object $aclInfo -Explode -ShowType -Label "Acl"
}
RobinBeismann commented 1 month ago

Thanks, I'll have to rewrite that for DirectoryServices ACLs but that should do. I'll prepare an example for runspaces and ACLs and open a bug over at the PowerShell.