Tuesday, 25 November 2014

Listing Configuration Manager Security Scopes Assigned to a Task Sequence

Today I had a problem. I wanted to create a spreadsheet that included the following information about task sequences in a customer's System Center 2012 SP1 Configuration Manager environment:

- Task sequence name
- Task sequence description
- Task sequence security scope

When listing this information to the screen it was OK, but when sending it to a .csv file, the 'SecuredScopeNames' was being recorded as 'SystemString' and not the actual value I wanted.

A colleague spent 20 minutes looking at this for me as I was lost and he figured it out. This is what he did. Pretty cool:


$ts = Get-CMTaskSequence

$ts | `
Select-Object Name, @{Name="SecuredScopeNames";Expression={($_.SecuredScopeNames -Join ",")}}, Description | `
Export-CSV `
  -Path "C:\Temp\Scopes-Task-Sequences.csv" `
  -Delimiter ";"  

Friday, 31 October 2014

PowerShell and Remote Services

Some quick notes on how to work with services on remote machines with PowerShell ....

Get all remote services on a target machine ...

Get-Service -ComputerName DB01


Get a specific service on a target machine ...

Get-Service -ComputerName DB01 -Name MSSQLSERVER


Get services based on part of the name on a target machine ...

Get-Service -ComputerName DB01  | Where name -match "sql"


Start a service on a target machine ...

Start-Service -InputObject `
               $(Get-Service -ComputerName DB01 -Name MSSQLSERVER)


Restart a service on a target machine ...

Restart-Service -InputObject `
               $(Get-Service -ComputerName DB01 -Name MSSQLSERVER)


Stop a service on a target machine ...

Stop-Service -InputObject `
               $(Get-Service -ComputerName DB01 -Name MSSQLSERVER)

Friday, 17 October 2014

Create the System Management Container with PowerShell

If you want System Center Configuration Manager to publish to Active Directory you have to extend the directory schema and create the System Management container in the System container. You then have to give site servers full control to the new object. Here's some Windows PowerShell to create the System Management container and set the required permissions on the new object. If the container already exists, the script will still assign permissions for a new site server. The script has been designed to run from the site server, not from another server.


# ========================================================
# SystemManagementContainer.ps1
#
# Purpose: Creates and/or configures the Active Directory System 
# Management container
#
# Author: JustAnotherTechnicalBlog 
# (http://justanothertechnicalblog.blogspot.com.au)
# 
# Version: 1.0
# 
# NOTES:
#
# 1. Creates the 'System Management' container required by 
#    Configuration Manager if it does not already exist
#
# 2. Sets permissions on the 'Systems Management' container 
#    required by site servers
#
# 3. Is designed to be run from the site server.  It configures
#    permissions for the host from where it is run.
#
# 4. No variables required
#
# 5. Does assume the Active Directory PowerShell module is 
#    available on the target machine
#
# ========================================================

# Get the distinguished name of the Active Directory domain
$DomainDN = (Get-ADDomain).DistinguishedName

# Get the AD computer object for this system
$ThisSiteSystem = Get-ADComputer $env:ComputerName 

# Build distinguished name path of the System container
$SystemDN = "CN=System," + $DomainDN

# Get or create the System Management container
$Container = $null 
Try 
 { 
    $Container = Get-ADObject "CN=System Management,$SystemDN" 
 } 
Catch 
 { 
    Write-Verbose "System Management container does not exist." 
 }

If ($Container -eq $null) 
 { 
    $Container = New-ADObject -Type Container -name "System Management" `
                                             -Path "$SystemDN" -Passthru 
 }

# Get current ACL for the System Management container
$ACL = Get-ACL -Path AD:\$Container

# Get the SID for the computer object
$SID = [System.Security.Principal.SecurityIdentifier] $ThisSiteSystem.SID

# Create a new access control entry for the System Management container
$adRights = [System.DirectoryServices.ActiveDirectoryRights] "GenericAll"
$type = [System.Security.AccessControl.AccessControlType] "Allow"
$inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] "All"
$ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
                                     $SID,$adRights,$type,$inheritanceType

# Add the new access control entry to the ACL object we grabbed earlier
$ACL.AddAccessRule($ACE)

# Commit the new audit rule
Set-ACL -AclObject $ACL -Path "AD:$Container"


Sunday, 28 July 2013

Joining a Domain with Windows PowerShell

Another quick Windows PowerShell post.  Once again I'm sitting in front of a newly built Windows Server 2012 machine running only Server Core.  This time I want to join the machine to my Active Directory domain.

All very easy with Windows PowerShell ...

New-Computer -Domain home.lab -Credential HOME\Administrator -Restart

Provide the password when prompted and wait for the machine to restart.

Easy easy easy .....

IP Address Configuration with Windows PowerShell

Once again I'm sitting in front of a newly built Windows Server 2012 machine running only Server Core in my lab at home.  This time I want to configure some IP address settings on the new machine.

The following Windows PowerShell commands get the job done:

Step #1

I need to get details about my network adapters so I run the following command.

Get-NetAdapter

Get-NetAdapter Results










Step #2

Now I can configure the adaptor I want.  I this case there is only one, so it is easy to select the correct one.  My address details are as follows:

IP: 192.168.33.10
Gateway: 192.168.33.1
Mask: 255.255.255.0

To configure this configuration I run the following command:

New-NetIPAddress -IPAddress 192.168.33.10 `
   -Default Gateway 192.168.33.1 `
   -AddressFamily IPv4 `
   -PrefixLength 24 `
   -InterfaceIndex 19

New-NetIPAddress Results

















Step #3

Finally I want to configure some DNS settings. This is the command I run:

Set-DnsClientServerAddress `
       -ServerAddress 192.168.33.2 `
       -InterfaceIndex 19
                  

That's it!!! Easy.

Friday, 26 July 2013

Rename a Computer Using Windows PowerShell

Short and sweet.  I'm sitting in front of a newly built Windows Server 2012 machine running only Server Core and I want to rename the machine.  It is a new machine not yet in a domain and I'm logged in with the default Administrator account.

It is easy with Windows PowerShell ...

Rename-Computer -NewName LABSVR2 -Restart

How easy is that?

Saturday, 13 July 2013

SQL 2012 on Windows Server 2012 Core - Firewall Configuration

Here is a quick one, only because I messed around missing the obvious after installing SQL 2012 when not being able to connect to the database after installation.  Once I went back to basics and realised the issue was the firewall, I used the following command to configure the Windows Firewall on my Windows Server 2012 Core machine so I could connect to SQL:

netsh advfirewall firewall add rule name="SQL Server 1433" 
  dir=in action=allow protocol=TCP localport=1433

NOTE: The command is wrapped, it should be a single line

Monday, 29 April 2013

Adding Audit Rules (SACLs) to Active Directory Objects

As part of the work I'm currently doing with Active Directory, my customer requires auditing of user, group and computer object deletions.  The group policy setting "Audit Directory Service Changes" enables the required auditing at an audit policy level, but the system access control lists (SACLs) for the objects don't include deletions by default.  I needed a way to configure all user, group and computer objects in the domain to include such a SACL entry.

Firstly, what are SACLs?  SACLs identify the users and groups that you want to audit when they successfully access or fail to access an object and can be configured not only to include the user or group you are interested in, but also the type of access.  The following screen grab shows the default auditing configured at the root of a new Windows Server 2012 Active Directory domain.


Default auditing on the root of a W2K12 Active Directory



I wanted to configure the SACLs as a task sequence action during the System Center Configuration Manager OSD task sequence I have developed for my customer, so I turned to Windows PowerShell.  After running my script, the auditing configured at the root of the domain looks like this:


Auditing on the root of the domain after the script has run


This is the script I came up with:



#------------------------------------------------------
# | File : ADDSAuditSettings.ps1                                        
# |                                            
# | Purpose : Configures extra auditing (SACLs) at for the
# | new domain
# |
# | Usage : PowerShell.exe -FILE .\ADDSAuditSettings.ps1 
#------------------------------------------------------
# |                                         
# | Author:          JustAnotherTechnicalBlog
# | Creation Date:   26 April 2013
# |
# |
# | Maintenance History                                            
# | ------------------- 
# | 
# | Version:  1.00  2013-04-26  Initial Version  JustAnotherTechnicalBlog
# |
# |
#------------------------------------------------------


# Clear the error variable
#------------------------------------------------------
$error.clear()


# Import the ActiveDirectory PowerShell Module if required
#------------------------------------------------------
if (-not (Get-Module ActiveDirectory))
  {
   Import-Module ActiveDirectory
  }

# This fuction takes a schema GUID ID and a security  
# principal and enables a new SACL entry so deletions
# of target object type by the specified security 
# principal will be audited
#------------------------------------------------------
Function AuditDeletions {

  Param (
         [Parameter(Mandatory=$true)]
         [system.guid]$SchemaIDGUID,
         [Security.Principal.NTAccount]$SecurityPrincipal  
        )

  # Get the DN for the current domain
  #------------------------------------------------------
  $dn = (Get-ADDomain).DistinguishedName

  # Get the current ACLs for the root of the domain
  #------------------------------------------------------
  $acl = Get-ACL -Audit -Path AD:\$dn

  # Build the new SACL rule.
  # This rule will enable auditing of succesful deletion 
  # of our target object.  The rule will be inherited 
  # throughout the domain
  #------------------------------------------------------
  $Rule = New-Object System.DirectoryServices.ActiveDirectoryAuditRule `
                     $SecurityPrincipal, `
                     "DeleteChild", `
                     "Success", `
                     $SchemaIDGUID, `
                     "All"

  # Add the new audit rule to the ACL we 
  # opened earlier
  #------------------------------------------------------
  $acl.AddAuditRule($Rule)

  # Commit the new audit rule
  #------------------------------------------------------
  Set-ACL -Path AD:\$dn -AclObject $acl

}


# To work with AD objects we need the relevent schema
# ID GUIDs. variables to hold these:
#------------------------------------------------------
$ComputerSchemaIDGUID = "bf967a86-0de6-11d0-a285-00aa003049e2"
$GroupSchemaIDGUID    = "bf967a9c-0de6-11d0-a285-00aa003049e2"
$UserSchemaIDGUID     = "bf967aba-0de6-11d0-a285-00aa003049e2"


# The AuditDeletions function above requires a security 
# principal.  user/group we want to audit?
#------------------------------------------------------
$who = "Everyone"


# Put the AuditDeletions function to use ....
#------------------------------------------------------
AuditDeletions $ComputerSchemaIDGUID $who
AuditDeletions $GroupSchemaIDGUID $who
AuditDeletions $UserSchemaIDGUID $who


# Basic error handling
#------------------------------------------------------
If ($error)
  {
   Write-Host "Audit setting configurations failed"
   Exit 1003
  }
Else
  {
   Write-Host "Audit setting configurations completed OK"
  }

Tuesday, 23 April 2013

Automating Active Directory Setup - Install a Child Domain

In previous posts over the past few weeks I've explained how I've installed the Active Directory Domain Services role and provisioned the first domain controller in a root domain using Configuration Manager OSD task sequences and some Windows PowerShell code. The next thing I need to do is install the first domain controller in a subordinate child domain in the new forest. The child domain will hold all my computing resources and users.

The following script:

  • Installs a new domain controller in a child domain, creating that new domain.
  • Gets the variables you will see in the script from Configuration Manager.
  • Creates the new domain within the previously created forest
  • Ensures DNS delegations are created
#-------------------------------------------------------------------
# | File : NewChildDomain.ps1                                           
# |                                            
# | Purpose : Installs the first Domain Controller in a child domain, 
# |           thus creating the new domain
# |           - Designed to be run from a Configuration Manager OSD 
# |             task sequence
# |           - Designed for Windows Server 2012 environments
# |           - Reboot handled by task sequence
# |
# | Usage : PowerShell.exe -FILE .\NewChildDomain.ps1 
#-------------------------------------------------------------------
# |                                         
# | Author:          JustAnotherTechnicalBlog
# | Creation Date:   23 April 2013
# |
# |
# | Maintenance History                                            
# | ------------------- 
# | 
# | Version:  1.00  2013-04-23  Initial Version  JustAnotherTechnicalBlog
# |
# |
#-------------------------------------------------------------------


# Clear the error variable
#-------------------------------------------------------------------
$error.clear()


# Import the ActiveDirectory PowerShell Module if required
#-------------------------------------------------------------------
if (-not (Get-Module ActiveDirectory))
  {
   Import-Module ActiveDirectory
  }


# Here we get access to the Task Sequence variables
#-------------------------------------------------------------------
$objTSenv = New-Object -COMObject Microsoft.SMS.TSEnvironment


# Grab the data we need from the task sequence variables
#-------------------------------------------------------------------
$strTSNetBIOSName =  $objTSenv.Value("RoleVariable1")
$strTSDomainName  =  $objTSenv.Value("RoleVariable2")
$strTSPrntNBName  =  $objTSenv.Value("RoleVariable3")
$strTSPrntDmnName =  $objTSenv.Value("RoleVariable4")
$strTSPrntDmnAcct = "$strTSPrntNBName\" + $objTSenv.Value("RoleAccount2")
$strTSDNSAccount  = "$strTSPrntNBName\" + $objTSenv.Value("RoleAccount3")


# Convert our password to the data type required by Install-ADDSDomain
#-------------------------------------------------------------------
$secstrSafeModePassword = $objTSenv.Value("RoleAccountPassword1") | `
      ConvertTo-SecureString -asPlainText -Force


# Convert our accounts and passwords strings to the data type required
# by Install-ADDSDomain
#-------------------------------------------------------------------
$secstrDomainPassword = $objTSenv.Value("RoleAccountPassword2") | `
     ConvertTo-SecureString -asPlainText -Force
$DomainCreds = New-Object `
     System.Management.Automation.PSCredential("$strTSPrntDmnAcct",$secstrDomainPassword)

$secstrDNSPassword = $objTSenv.Value("RoleAccountPassword3") | `
     ConvertTo-SecureString -asPlainText -Force
$DNSCreds = New-Object `
     System.Management.Automation.PSCredential("$strTSDNSAccount",$secstrDNSPassword)



# Install our first forest Domain Controller, creating a new forest
#-------------------------------------------------------------------
Install-ADDSDomain `
  -Force `
  -NoRebootOnCompletion `
  -CreateDNSDelegation `
  -DomainType Child `
  -DomainMode Win2012 `
  -ParentDomainName "$strTSPrntDmnName" `
  -NewDomainNetBIOSName "$strTSNetBIOSName" `
  -NewDomainName "$strTSDomainName" `
  -SafeModeAdministratorPassword $secstrSafeModePassword `
  -DNSDelegationCredential $DNSCreds `
  -Credential $DomainCreds



# Basic error handling
#-------------------------------------------------------------------
If ($error)
  {
   Write-Host "Child domain creation failed"
   Exit 1001
  }
Else
  {
   Write-Host "Child domain created successfully"



Task Sequence Snippet:  Active Directory Installation

Installing an Active Directory Child Domain with Windows PowerShell

Monday, 15 April 2013

Tip - Using Active Directory Users & Computers to Manage Another Domain

Today a colleague asked me how to connect to our forest root domain from an admin workstation in our child domain when using Active Directory Users & Computers (ADUC).  The forest root domain contains only a small number of servers, and they all have Windows 2012 Standard (Core) installed so no GUI.  What he wanted to do was quickly look at something with ADUC an not mess around with Windows PowerShell.  I thought it would be easy, but it isn't as easy as I thought, I figured it out in the end, but was a bit surprised this isn't built into the GUI tools.

This is what we did.

1.  On the admin workstation (a child domain member) launched an elevated command prompt with an admin level account local to the child domain (and probably would have worked with an admin level account that was only a workstation admin)

2.  Run the following command using credentials from the parent domain:


runas /netonly /user:DOMAIN01\TechGuy "mmc.exe dsa.msc"


This worked a treat and my colleague was able to do what he needed to do.  Is there a better way?

Automating Active Directory Setup - Installing the Active Directory Domain Services Role

I've been working on a OSD task sequence to deploy Active Directory in a Windows 2012 environment for my current customer.  They have many environments in production, and many more in the development, testing and quality assurance environments, so this is something they need to be automated and repeatable.

The screen sot below shows the snippet of a larger task sequence that installs many different roles, features, and applications all in one task sequence.  Variables assigned to the computer object when we provision the computer object in Configuration Manager drive what roles, features and applications get installed.  I'm not going to show how that works here, but it may be something I explain in separate posts at some stage.

The first step to install Active Directory is to install the Active Directory Domain Services role.  The screen shots below show how that is done in the task sequence.  I just use Windows PowerShell to do this with the following command:

#-----------
PowerShell.exe -COMMAND Install-WindowsFeature -Name AD-Domain-Services `
   -IncludeManagementTools

The code above does not create an domain controller. It just installs the Active Directory Domain Services role.  Other steps in the task sequence see the server promoted to be a domain controller.

Including the 'IncludeManagementTools' option sees the appropriate management tools, and Windows PowerShell modules, get installed.  This works on both the standard and core installations of Windows, with the installer being intelligent enough to know what to install base on what edition of Windows Server is being installed.


Task Sequence Snippet:  Active Directory Installation


Installing the Active Directory Domain Services Role with Windows PowerShell

Friday, 12 April 2013

Automating Active Directory Setup - Installing the First Domain Controller in a Forest

I'm building a new Active Directory environment based on Windows Server 2012. This is a green-fields site, and the builds are automated using the OSD task sequences available in System Center Configuration Manager 2012. The first server I build in the domain is a domain controller in a place-holder root domain. The following script promotes a server to this be a domain controller and creates the new forest and domain. A previous post explains how I install the Active Directory Domain Services role.


The script below:

  • Installs a new domain controller in a forest root domain, creating that domain.
  • Gets the variables you will see in the script from Configuration Manager.


I will explain how to populate variables in Configuration Manager in a separate post in due course.

#------------------------------------------------------------------------------------
# | File : NewForest.ps1                                           
# |                                            
# | Purpose : Installs the first Domain Controller in a forest, thus creating 
# |           a new forest
# |           - Designed to be run from a Configuration Manager OSD task sequence
# |           - Designed for Windows Server 2012 environments
# |           - Reboot handled by task sequence
# |
# | Usage : PowerShell.exe -FILE .\NewForest.ps1 
#------------------------------------------------------------------------------------
# |                                         
# | Author:          JustAnotherTechnicalBlog
# | Creation Date:   11 April 2013
# |
# |
# | Maintenance History                                            
# | ------------------- 
# | 
# | Version: 1.00 2013-04-12      Initial Version      JustAnotherTechnicalBlog
# |
# |
#------------------------------------------------------------------------------------


# Clear the error variable
#------------------------------------------------------------------------------------

$error.clear()



# Import the ActiveDirectory PowerShell Module if required
#------------------------------------------------------------------------------------

if (-not (Get-Module ActiveDirectory))
  {
   Import-Module ActiveDirectory
  }



# Here we get access to the Task Sequence variables
#------------------------------------------------------------------------------------

$objTSenv = New-Object -COMObject Microsoft.SMS.TSEnvironment



# Grab the data we need from the task sequence variables
#------------------------------------------------------------------------------------

$strTSNetBIOSName         = $objTSenv.Value("RoleVariable1")
$strTSDomainName          = $objTSenv.Value("RoleVariable2")



# Convert our password to the data type required
# by Install-ADDSForest
#------------------------------------------------------------------------------------

$secstrSafeModePassword = $objTSenv.Value("RolePassword1") | `
   ConvertTo-SecureString -asPlainText -Force



# Install our first forest Domain Controller, creating a new forest
#------------------------------------------------------------------------------------

Install-ADDSForest `
  -Force `
  -NoRebootOnCompletion `
  -DomainNetBIOSName "$strTSNetBIOSName" `
  -DomainName "$strTSDomainName" `
  -ForestMode Win2012 `
  -DomainMode Win2012 `
  -SafeModeAdministratorPassword `
        $secstrSafeModePassword



# Very basic error handling ...
#------------------------------------------------------------------------------------

If ($error)
  {
   Write-Host "Forest creation failed"
   Exit 1000
  }
Else
  {
   Write-Host "Forest created successfully"
  }


Task Sequence Snippet:  Active Directory Installation


Installing a new forest with a PowerShell script