dsccommunity / SecurityPolicyDsc

A wrapper around secedit.exe to configure local security policies
MIT License
177 stars 53 forks source link

UserRightsAssignment: Multiple resources defining same policy in a single configuration not possible #104

Open danielboth opened 6 years ago

danielboth commented 6 years ago

Details of the scenario you tried and the problem that is occurring

The UserAssignmentResource cannot be used multple times in the same configuration to set the same policy. In a single configuration, this is not useful, in a scenario where composite / partial configurations are used though, being able to use the resource in multiple partial configurations is very useful.

Verbose logs showing the problem

Error generated while compiling the configuration:

Test-ConflictingResources : A conflict was detected between resources '[UserRightsAssignment]LogonAsService1 (::7::9::UserRightsAssignment)' and '[UserRightsAssignment]LogonAsService2 (::14::9::UserRightsAssignment)' in node 'localhost'. Resources have identical key properties but there are differences in the following non-key properties: 'Identity'. Values 'System.Object[]' don't match values 'System.Object[]'. Please update these property values so that they are identical in both cases.

Suggested solution to the issue

The fix is easy, we can just change the Identity to key on the schema, which would fix this issue. See here:

https://github.com/PowerShell/SecurityPolicyDsc/blob/9dd5b09192622c9a93a941c7b1a334b925defd8b/DSCResources/MSFT_UserRightsAssignment/MSFT_UserRightsAssignment.schema.mof#L6

The DSC configuration that is used to reproduce the issue (as detailed as possible)

Configuration LogonAsService {

    Import-DscResource -ModuleName @{ModuleName = 'SecurityPolicyDsc'; ModuleVersion = '2.5.0.0'}

    Node localhost
    {
        UserRightsAssignment 'LogonAsService1'
        {
            Policy = 'Log_on_as_a_service'
            Identity = @('Account1')
            Ensure = 'Present'
        }

        UserRightsAssignment 'LogonAsService2'
        {
            Policy = 'Log_on_as_a_service'
            Identity = @('Account2', 'Account3')
            Ensure = 'Present'
        }
    }
}

LogonAsService

The operating system the target node is running

Happens on any OS.

Version and build of PowerShell the target node is running

5.1

Version of the DSC module that was used ('dev' if using current dev branch)

2.5.0.0

I'm happy to create the PR if we agree this is a good way forward.

johlju commented 6 years ago

I understand the problem, unfortunately an array cannot be a Key.

The problem you are having is a common one when using partials, because then we think of the configurations as separate units. But DSC sees the whole as one unit. The unique here (in your example) is that that the desired state is that Policy Log_on_as_a_service, and that should be set to @('Account1','Account2', 'Account3') to be in desired state. It would be easy to think to add any other (dummy) property as Key would help, but that would introduce a ping-pong behavior, especially when using partial (if configurations are written wrong by mistake), so the configuration will never be in desired state. Today the configurations must be built to handle that the resulting mof file is one unit and all Keys must be unique.

danielboth commented 6 years ago

You are right, I compiled a configuration using Identity as key (which works fine btw), so that made me think it could be done. At execution time I get an error "failed to register MOF classes" though, so indeed, that approach does not seem to work :(.

The ping-pong behavior you are describing is not something I see as an issue though, other resources in this module have the property "Description' as their key. That property is not used within the resource. That works, since you can just have a different description. Sure, that also means you can have conflicting resources, that's the price to pay for flexibility.

Like you said, adding an extra property 'Description' as key to this resource would already solve my problem here. Would a PR implementing that as a solution be accepted?

johlju commented 6 years ago

Like you said, adding an extra property 'Description' as key to this resource would already solve my problem here. Would a PR implementing that as a solution be accepted?

I leave that up to the community and @jcwalker (maintainer). 🙂

jcwalker commented 6 years ago

I'm hesitant to accept something like this since adding a Name property will introduce a braking change since all key parameters are mandatory. This will require everyone to modify their existing configurations to use the latest version of the resource. This will need to be a popular request from the community to be accepted.

@danielboth is it possible to deconflict the resources in your scenario?

danielboth commented 6 years ago

@jcwalker, it's not possible to deconflict the resources in this case. Also, I would like to give another scenario that would be solved by implementing a second key property. That would be a configuration where both an account is added and one is removed. Currently, it is not possible to write this configuration:

Configuration LogonAsService {

    Import-DscResource -ModuleName @{ModuleName = 'SecurityPolicyDsc'; ModuleVersion = '2.5.0.0'}

    Node localhost
    {
        UserRightsAssignment 'LogonAsService1Present'
        {
            Policy = 'Log_on_as_a_service'
            Identity = @('Account1')
            Ensure = 'Present'
        }

        UserRightsAssignment 'LogonAsService2Absent'
        {
            Policy = 'Log_on_as_a_service'
            Identity = @('Account2')
            Ensure = 'Absent'
        }
    }
}

LogonAsService

Since we have both absent and present possible, it should be possible to use both?

johlju commented 6 years ago

That would be solved to make Ensure a Key, and each configuration should be unique. But that differs from the previous suggestion as Ensure as Key would not make a ping pong behavior as Ensure would only allow two values.

jcwalker commented 6 years ago

@danielboth does using the Force parameter help any? In the example below only Account1 will be assigned 'Log on as a service'


Configuration LogonAsService {

    Import-DscResource -ModuleName @{ModuleName = 'SecurityPolicyDsc'; ModuleVersion = '2.5.0.0'}

    Node localhost
    {
        UserRightsAssignment 'LogonAsService1Present'
        {
            Policy = 'Log_on_as_a_service'
            Identity = @('Account1')
            Ensure = 'Present'
            Force = $true
        }
    }
}

LogonAsService

LogonAsService
stale[bot] commented 6 years ago

This issue has been automatically marked as stale because it has not had activity from the community in the last 30 days. It will be closed if no further activity occurs within 10 days. If the issue is labelled with any of the work labels (e.g bug, enhancement, documentation, or tests) then the issue will not auto-close.

stale[bot] commented 5 years ago

This issue has been automatically closed because it is has not had activity from the community in the last 40 days.

jcwalker commented 5 years ago

I wanted to reopen this, as this seems to constantly come up, and ask the community for feedback.

Here are the solutions that have been suggested in the past:

  1. Add a Description parameter as a key
  2. Make Identity a key parameter which means it couldn't be an array anymore. If multiple identiies are required to be on a policy then a composite could be used like WindowsFeature and WindowsFeatureSet.
  3. Model the Group resource and have a property to remove and add identities (IdentitiesToInclude/IdentitiesToExclude).

All of these are breaking changes so I'm not a big fan of any of them but if a change would benefit the community then I could be a fan :).

rafnijs commented 4 years ago

I'm havingthe same issue, I use a security baseline (composite resources) define the baseline as a module. Some machines need to have an exception on a entry which also included in my baseline.

The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: A conflict was detected between resources '[UserRightsAssignment]CCE-37072-6: Allow log on through Remote Desktop Services::[sb2012r2]registry (C:\Modules\User\sb2012r2\DSCResources\sb2012r2\sb2012r2.schema.psm1::983::4::UserRightsAssignment)' and '[UserRightsAssignment]RDP-Logon-Rights (::85::1::UserRightsAssignment)' in node 'MACHINENAMVE'. Resources have identical key properties but there are differences in the following non-key properties: 'Identity;Ensure'. Values 'System.Object[];NULL' don't match values 'System.Object[];Present'. Please update these property values so that they are identical in both cases.