close

DSC

AutomationDevOpsDSCPowershell

Managing User Rights in Powershell

LocalSec

Managing User Rights Assignments in Powershell

Windows User Rights, also known as Windows Privileges, are traditionally managed via GPO or in the simplest of cases via the server’s Local Security Policy. These assignments control special permissions that are often needed by IIS applications or other application hosting on Windows Servers.

So how can we manage these assignments in Powershell? There’s no obvious solution provided in Powershell, but there are several options are available. None of which are a pure Powershell solution, but some are close.

  • Wrap the ntrights.exe process in Powershell. This is relatively simple, but the downside is having an external dependency on the ntrights.exe file.
  • Embed a wrapper class to the LSA API in your script. This is a pretty good solution but certainly bloats your script.
  • Load and Reference the Carbon DLL (If you haven’t already checked out this Powershell library, you should it is very powerful and regularly updated. I choose this approach because it keeps the script clean and compact, it returns an array of strings for easy interrogation. It does require a dependency on carbon.dll, but this library provides a ton of functionality beyond just this.

I like the 3rd option, its very clean, and I like working with the Carbon library.

Example Script

  param (
    [Parameter(Mandatory=$true)]
	[string]$identity,
	[Parameter(Mandatory=$true)]
	[string]$privilege,
	[Boolean]$grant)

# Path to Carbon DLL
$CarbonPath = "\\ManagementServer\Store\Carbon.dll"

# Load Carbon Assembly
[Reflection.Assembly]::LoadFile($CarbonPath) | Out-Null

# Grant Privilege if flag is set
if ($grant){ [Carbon.Lsa]::GrantPrivileges( $Identity , $privilege )}

# Read Privileges
$result = [Carbon.Lsa]::GetPrivileges($Identity) | Where-Object { $_ -eq $Privilege }

# Display Output
if ($result -eq $null){
	Write-Host "$identity does NOT have $privilege"
} else {
	Write-Host "$identity has the $privilege"
}

Now lets take this script to the next level and wrap it into a DSC Script implementation. We can use this same logic in a DSC configuration to make sure our desired User Rights Assignments are kept in place.

DSC Example

$Identity = "domain\bpate"
$privilege = "SeServiceLogonRight"
$CarbonPath = "\\ManagementServer\Store\Carbon.dll"

Configuration WindowsPrivilegeExample
{
  Node NodeName
   {
    	Script Grant-SeServiceLogonRight
        {
           GetScript = {
		   	[Reflection.Assembly]::LoadFile($CarbonPath) | Out-Null

			$result = [Carbon.Lsa]::GetPrivileges($Identity) | Where-Object { $_ -eq $Privilege }
			
			if ($result -eq $null) { return @{ Privilege = "Not Granted" }}
			else { return @{ Privilege = "Granted" } }
		   }
           TestScript = { 
		   	[Reflection.Assembly]::LoadFile($CarbonPath) | Out-Null

			$result = [Carbon.Lsa]::GetPrivileges($Identity) | Where-Object { $_ -eq $Privilege }
    		return ($result -ne $null)
		   }
           SetScript = {	   
			[Reflection.Assembly]::LoadFile($CarbonPath) | Out-Null

			[Carbon.Lsa]::GrantPrivileges( $Identity , $privilege )

		   }
        }
		
	}
}

What else can we do? We could also create a Custom DSC Resource to have a cleaner DSC Configuration.


read more
AutomationDSCPowershellUncategorized

Custom DSC Resource Schema

no thumb

Windows Powershell Desired State Configuration (DSC) allows you to build custom resources to implement new functionality. When creating my first custom resource I stumbled across a few gotchas in the TechNet documentation. After using the TechNet example MOF Schema I hit a few errors. My assumption is this is due to changes from the preview version to the actual release version.

TechNet Example Schema

[version("1.0.0"), FriendlyName("Website")] 
class Demo_IISWebsite : MSFT_BaseResourceConfiguration
{
  [Key] string Name;
  [write] string PhysicalPath;
  [write,ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] string Ensure;
  [write,ValueMap{"Started","Stopped"},Values{"Started", "Stopped"}] string State;
  [write,ValueMap{"http", "https"},Values{"http", "https"}] string Protocol[];
  [write] string BindingInfo[];
  [write] string ApplicationPool;
  [read] string ID;
};

The first error occurred when generating the MOF files.
DSC-Error

Fix: I opened the schema files that were installed, they inherited from “OMI_BaseResource” not “MSFT_BaseResourceConfiguration

The second error was rather cryptic when trying to apply the MOF to the machine. ClassVersion Qualifier not found.
DSC-Error

Fix: As with the first error, the documentation refers to a class attribute called “Version“, but it should be “ClassVersion” instead.

Working Schema

[ClassVersion("1.0.0"), FriendlyName("Website")] 
class Demo_IISWebsite : OMI_BaseResource
{
  [Key] string Name;
  [write] string PhysicalPath;
  [write,ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] string Ensure;
  [write,ValueMap{"Started","Stopped"},Values{"Started", "Stopped"}] string State;
  [write,ValueMap{"http", "https"},Values{"http", "https"}] string Protocol[];
  [write] string BindingInfo[];
  [write] string ApplicationPool;
  [read] string ID;
};
read more
AutomationDSCPowershell

Windows Powershell Desired State Configuration

no thumb

With the release of Powershell 4.0, we can now leverage Powershell DSC across Server 2012 and Server 2008 R2. This is a pretty good foot print for supporting any modern infrastructure. In my opinion, DSC is one of the most powerful features to be added to Powershell since WinRM. It provides a great foundation for generating very solid infrastructure automation for Windows Servers.

There’s a number of great resources for learning DSC, see the links below. But I’ll summarize the key features.

  • Ability to define using declarative scripting the server configuration. This is a huge improvement over traditional scripts, because they’re easier to implement and maintain over time. This functionality has existed in the Linux world for some time using tools like CFEngine, Puppet, and Chef. But it was clunky to implement for Windows.
  • Ability to separate data from configuration declarations.
  • Ability to implement custom functionality. Out of the box DSC comes with a number of basic resources that cover most situations, but implementing custom functionality is not very difficult.

Example

# Config Values
$ApplicationSource = "\\ATL0WSRCP001\Applications\MyApp"

Configuration MyWebConfig
{
   Node "ATL0WIISP001"
   {
      # This ensures the Web Server (IIS) role is installed
      WindowsFeature IIS7-Install
      {
          Ensure = "Present"
          Name = "Web-Server"  
      }

      # File is a built-in resource you can use to manage files and directories
      # This example ensures files from the source directory are present in the destination directory
      File Application-Files
      {
         Ensure = "Present"
         Type = "Directory"
         Recurse = $true
         SourcePath = $ApplicationSource # This is a path that has the source files
         DestinationPath = "E:\Applications\MyApp" # The path where we want to ensure the web files are present
         Requires = "[WindowsFeature]IIS7-Install"  # This ensures that IIS7-Install completes successfully before this block runs
      }
   }
}

Resources

read more