Automating DCOM ACL with PowerShell

Sometimes you need to set explicit permissions on DCOM objects. You can do this using dcomcnfg.exe. With dcomcnfg.exe you can set permissions on all DCOM objects on a computer. However, this is doing it manually. 🙂 If you ever need to automate this step, you can do it using PowerShell, and here is how. Please note you have to run PowerShell as Administrator.

dcomcnfg

Automating DCOM ACL with PowerShell

There are 5 steps to configure DCOM ACL.

1.) Get WMI object

2.) Get Descriptor

3.) Create Trustee and assign it rights

4.) Add Trustee to Descriptor

5.) Set WMI object

In step one, we get WMI object for DCOM application we want to set permissions. In below example, we get settings for Messaging application

$wmi = Get-WmiObject -Class Win32_DCOMApplicationSetting -Filter ‘caption=”Messages”‘ -EnableAllPrivileges

In step two we get current security descriptor for this object, so we can add permissions to existing set. We can get and set permissions for all 3 types

$descL = $wmi.GetLaunchSecurityDescriptor().descriptor
$descA = $wmi.GetAccessSecurityDescriptor().descriptor
$descC = $wmi.GetConfigurationSecurityDescriptor().descriptor

Image from GUI:

dcomcnfgSec

In step three we create our own trustee object, which we will use to assign rights to. It consists of Domain, username and permissions we would like to assign to it. In this example we will set all permissions to allow to user object Interactive.

$trusteeObj = ([wmiclass]’Win32_Trustee’).psbase.CreateInstance()
$trusteeObj.Domain = “NT authority”
$trusteeObj.Name = “Interactive”

$ace = ([wmiclass]’Win32_ACE’).psbase.CreateInstance()
$ace.AccessMask = 31
$ace.trustee = $trusteeObj

If you need to set different permissions then in example above, you can get AccesssMask values by manually setting permissions in GUI as you need them and then read them using PowerShell. In step two we got current descriptor, from which we can read current permissions.

First we need to get DACL list:

$descL.[X].DACL

in this object you have current Trustee and it’s AccessMask.

From here on it is very simple…

In step four we add our object we created in step 3 to descriptor

$descL.DACL += [System.Management.ManagementBaseObject]$ace
$descA.DACL += [System.Management.ManagementBaseObject]$ace
$descC.DACL += [System.Management.ManagementBaseObject]$ace

And in step five we write is back using WMI.

$wmi.SetLaunchSecurityDescriptor($descL)
$wmi.SetAccessSecurityDescriptor($descA)
$wmi.SetConfigurationSecurityDescriptor($descC)

We can see the changes we made using dcomcnfg.exe or PowerShell

dcomcnfgSec2

Again, do not forget to run PowerShell as Administrator! 😉

Code is available for download on TechNet:

https://gallery.technet.microsoft.com/Set-DCOM-ACL-with-650fa48d

Hope this helps you.

16 thoughts on “Automating DCOM ACL with PowerShell

  1. I believe you mean
    $wmi.SetLaunchSecurityDescriptor($descL)
    $wmi.SetAccessSecurityDescriptor($descA)
    $wmi.SetConfigurationSecurityDescriptor($descC)

    instead of

    $wmi.SetLaunchSecurityDescriptor($descL)
    $wmi.SetAccessSecurityDescriptor($descA)
    $wmi.SetAccessSecurityDescriptor($descC)

    Like

  2. Trying this on MsDtsServer120 application and all descriptors are empty and can’t process any further with setting up local user group to have access to this application (OS 2012, SQL 2014). Any idea? Thanks

    Like

      • Here’s part of the code where $srv is simply another new-object where ComputerNamePhysicalNetBIOS provides the server name instead of SQL instance. Then I will finish with the 3 set commands.
        I’m not sure that the trustee is the issue but rather the empty descriptor from the DCOM application itself.

        $Name = ‘Distributed COM Users’
        $ComputerName = $srv.ComputerNamePhysicalNetBIOS
        #Get wmi object
        $wmi = Get-WMIObject -Class Win32_DCOMApplicationSetting -Filter ‘LocalService like “MsDtsServer%”‘ -EnableAllPrivileges

        #Get Security Descriptors
        $descL = $wmi.GetLaunchSecurityDescriptor().descriptor
        $descA = $wmi.GetAccessSecurityDescriptor().descriptor
        $descC = $wmi.GetConfigurationSecurityDescriptor().descriptor

        #Create the Trusteee Object
        $trusteeObj = ([wmiclass]’Win32_Trustee’).psbase.CreateInstance()
        $trusteeObj.Domain = $ComputerName
        $trusteeObj.Name = $Name

        Thanks

        Like

      • Hi,

        When I run your $wmi = … command it fails. Does $wmi variable at your end contain any value, or does it return error?

        Try running the following:
        $wmi = Get-WMIObject -Class Win32_DCOMApplicationSetting -Filter “LocalService like ‘MsDtsServer%'” -EnableAllPrivileges

        PS: sometimes single quotes get messed up by HTML, try retyping them.

        Like

      • Hi JanBK,
        Understandably, these quote issues do happen with copy pasting. For example, in copying over your line, poweshell would not parse it. So I had to replace them with my US english culture. Reversing the quotes provides the same info for the $wmi object. I’m curious to know if you do have SQL set up in your environment and can see securitydescriptors for MsDtsServer.
        Thanks
        Charbs

        Like

      • Hi charbs,

        I just tried on my test SQL, it works here, but PowerShell has to run as admin, if I start it as non elevated user, then I get empty descriptor. Did you try it from elevated PowerShell?

        Like

      • Got it working . The only thing left is to understand the mask for the Configuration Permissions descriptor. The 31 doesn’t reflect the Full Control and Read values.
        Thanks again.
        Charbs

        Like

  3. You know it’s going to be one of those days when…..
    I just realised that I’m in the middle of configuring a new SQL installation and testing various scripts. It’s Microsoft after all.
    Reboot !
    Now I can see results in my descriptors. Sorry for the run around on that point.

    The only thing now is that I don’t have anything set when I check in the GUI. The ‘Distributed COM Users’ local group doesn’t appear in the three Security Descriptors.
    I do have that new trustee in the descL and others though.
    I wonder if there’s an alter() somewhere to set things properly.
    Thanks
    Charbs

    Like

    • Thanks for everything JanBK
      The domain needs to be ‘BUILTIN’ for any local groups.
      The Full Control for MsDTSServer Configuration Access is 983103 and Special Permission 268435456 so I simply reused the same $ace with each value and set the descriptor accordingly.
      Charbs

      Like

  4. Going out on a limb here but do you happen to know how to convert the security descriptors from the registry to a human readable format?

    Reason being, when querying the Access DACL, its ’empty’:
    (gwmi Win32_DCOMApplicationSetting -Filter “AppID='{9CA88EE3-ACB7-47c8-AFC4-AB702511C276}'” -EnableAllPrivileges).GetAccessSecurityDescriptor().descriptor

    __GENUS : 2
    __CLASS : Win32_SecurityDescriptor
    __SUPERCLASS : __SecurityDescriptor
    __DYNASTY : __SecurityRelatedClass
    __RELPATH :
    __PROPERTY_COUNT : 6
    __DERIVATION : {__SecurityDescriptor, __SecurityRelatedClass}
    __SERVER :
    __NAMESPACE :
    __PATH :
    ControlFlags : 32788
    DACL : {}
    Group : System.Management.ManagementBaseObject
    Owner : System.Management.ManagementBaseObject
    SACL : {}
    TIME_CREATED :
    PSComputerName :

    And of course hen going accessing the AppID in question (e.g.: RuntimeBroker) via the GUI, it gives me the option to remove those permissions which is great. But I’d still like to know what they are, even if they are invalid, before I fix them.

    Thanks!

    Like

  5. Pingback: DCOM machine access and launch permissions help - How to Code .NET

  6. The description seems to be right along the lines of what I need to do. But I’m not able to translate into another specific situation. What Object do I need? Where is the list of Objects to choose from and what is it called? Even with Powershell. etc. All that is quite a leap.
    The manual instructions for what I need are pretty simple:
    *****
    DCOMCNFG.EXE
    Computers / My Computer / Properties / COM Security/ Launch and Activate Permissions / Limits
    … add [user name]
    … Permissions for [user name] ALLOW all
    *****
    Might it be possible to get a little more “glue”.
    Thanks!!

    Like

  7. I can almost get this to work the way I want it. However, the Configuration Security gets set to ‘Special permissions’. How do I set it to ‘Full Control’ and ‘Read’?
    Thanks

    Like

  8. Thanks for this. It works… but with one caveat… you must have already added the Component Services snapin. Is there a way to do that programmatically?
    Thanks

    Like

Leave a reply to JanBK Cancel reply