PowerShell : How do I create Trust ?

Standard

A question was raised on ActiveDir regarding the ability to create Trust via a command line utility. It was discussed how netdom is no longer a supported command line utility to create Trusts. I referenced a snip from AD Cook Book using PowerShell to create Trust via the .Net AD namespace method alternatively.(System.DirectoryServices.ActiveDirectory).

You can use following code to create a two-way transitive trust between the local forest and a remote forest. You will have to run this code on the opposite side of the trust in order for the trust to be fully functional.

$localfor=[System.DirectoryServices.ActiveDirectory.Forest]::getCurrent()
$strRemoteFor='remotedomain.net'
$strRemoteUser='administrator'
$strRemotePass='P@ssw0rd'
$remoteCon=New-Object
System.DirectoryService.ActiveDirectory.DirectoryContext('Forest',
$strRemoteFor,$strRemoteUser,$strRemotePass)
$trustDirection='BiDirectional'$localFor.CreateTrustRelationship
($remoteFor,$trustDirection)

Server Core R2 DC promotion fails due to unavailable ADDS binaries

Standard

I encountered an issue promoting a Server Core R2 to a domain controller. The DCPROMO on Server Core is handled via unattended mode with answer file. The error I received is below. It was due to Server Core’s inability to install/confirm ADDS binaries.

C:UsersAdministrator>dcpromo /unattended:answer.txt
Checking if Active Directory Domain Services binaries are installed…
Failed to detect if Active Directory Domain Services binaries were installed. The error was: An error with no description has occurred.

And the DCPROMOUI.log also shed some light on the nature of the issue.

dcpromoui 504.204 001E 03:01:08.709     Unable to find identity string for package name Microsoft-Windows-ServerCore-Package
dcpromoui 504.204 001F 03:01:08.709   Failed to retrieve the parent package name
dcpromoui 504.204 0020 03:01:08.709   HRESULT = 0x800F0818
dcpromoui 504.204 0021 03:01:08.709   HRESULT = 0x800F0818
dcpromoui 504.31C 0022 03:01:08.709     HRESULT = 0x800F0818
dcpromoui 504.31C 0023 03:01:08.709   Enter GetErrorMessage 800F0818

My attempt to add the binaries via the DISM also failed.

dism /online /enable-feature /featurename:DirectoryServices-DomainController-ServerFoundation

Deployment Image Servicing and Management tool
Version: 6.1.7600.16385

Image Version: 6.1.7600.16385

Error: 0x800f0818

DISM failed. No operation was performed.
For more information, review the log file.

The DISM log file can be found at C:WindowsLogsDISMdism.log  

The OCSETUP attempt also failed sighting the same error.

ocsetup DirectoryServices-Domain-Controller-ServerFoundation

 

image

 

After I had ensured that the OS was up-to-date with patches and updates, I stumbled upon System Update Readiness Tool KB947821. What is System Update Readiness Tool ? it is a patch that helps you find the inconsistencies with system files.

System resources, such as file data, registry data, and even in-memory data, can develop inconsistencies during the lifetime of the operating system. These inconsistencies might be caused by various hardware failures or might be caused by software issues. In some cases, these inconsistencies can affect the Windows servicing store, and they can cause software updates not to work. The System Update Readiness Tool tries to resolve these inconsistencies.

The System Update Readiness Tool creates a log file that captures any issues that the tool found or fixed. The log file is located at the following location:

  • %SYSTEMROOT%LogsCBSCheckSUR.log
  • %SYSTEMROOT%LogsCBSCheckSUR.persist.log

On this Server Core, the CheckSUR.log indicated issues with two files (its an update specific MUM file with its catalog file), that the tool found to be corrupted.

Checking System Update Readiness.
Binary Version 6.1.7600.20822
Package Version 10.0
2011-02-19 20:53

Checking Windows Servicing Packages

Checking Package Manifests and Catalogs
(f)    CBS MUM Corrupt    0x00000000    servicingPackagesPackage_for_KB2207566_RTM~31bf3856ad364e35~amd64~~6.1.1.0.mum        Expected file name Microsoft-Windows-ServerCore-Package~31bf3856ad364e35~amd64~~6.1.7600.16385.mum does not match the actual file name

Checking Package Watchlist

Checking Component Watchlist

Checking Packages

Checking Component Store

Summary:
Seconds executed: 165
Found 1 errors
  CBS MUM Corrupt Total count: 1

Unavailable repair files:
    servicingpackagesPackage_for_KB2207566_RTM~31bf3856ad364e35~amd64~~6.1.1.0.mum
    servicingpackagesPackage_for_KB2207566_RTM~31bf3856ad364e35~amd64~~6.1.1.0.cat

I also came across this Technet forum post, which is similar in nature but is applicable to different corrupt files with different symptoms, however it was this post that gave me the idea to fix my problem.

Solution :

1. I downloaded the KB2207566 (Windows6.1-KB2207566-x64.msu) as indicated by SUR log, and copied it to Server Core (c:temp). Note that this patch already had been installed but for some reason had the mentioned files corrupted.

2. I then extracted the MSU file into a sub folder and extracted the *.cab files.

C:UsersAdministrator>cd c:temp

c:temp>wusa Windows6.1-KB2207566-x64.msu /extract:c:servicingkb2207566

c:temp>cd kb2207566

c:tempkb982214>mkdir files

c:tempkb982214>expand Windows6.1-KB2207566-x64.cab -F:* files

The two files I had to replace were these :

image

The location for the existing files that had to be replaced was c:windowsservicingpackages and an issue I ran into, as it was indicated on the Technet post (when I simply attempted to UNC and copy from another regular W2K8 machine) was that these were protected files and the copy/create option was denied. Lot of systems folders/files in Windows 7 and Windows Server 2008 have a different owner than ‘administrators’ and the TrustedInstaller is set as owner and has full control rights set.

image

3. And I then opted to use the command line option to take the ownership of the folder and assign ‘administrators’ the full rights on the Server Core.

takeown /f c:windowsservicingpackages /r /d y

icacls c:windowsservicingpackages /grant administrators:F /T

4. And lastly I copied the extracted files and replaced.

C:tempkb982214files>copy "package_for_kb2207566_rtm~31bf3856ad364e35~amd64~~6
.1.1.0.cat" c:WindowsservicingPackages

Overwrite c:WindowsservicingPackagespackage_for_kb2207566_rtm~31bf3856ad364e
35~amd64~~6.1.1.0.cat? (Yes/No/All): y
      

1 file(s) copied.

C:tempkb982214files>copy "package_for_kb2207566_rtm~31bf3856ad364e35~amd64~~6
.1.1.0.mum" c:WindowsservicingPackages

Overwrite c:WindowsservicingPackagespackage_for_kb2207566_rtm~31bf3856ad364e
35~amd64~~6.1.1.0.mum? (Yes/No/All): y

1 file(s) copied.

No restart was required and the DCPROMO with the answer file succeeded as it was now able to install the ADDS binaries and the DC promoted successfully.

Note that prior to the fix I also noticed that I was unable to enable the remote management from the SCONFIG (option 4, sub option 3) which also worked afterwards.

Exchange 2010 Setup and .Net Framework 3.5 SP1 Requirement

Standard

Starting with Exchange 2007, the good thing about the setup wizard is that it guides you about all the pre-requisites and provides the links from where you can download them from.

image

However, if you are installing Exchange 2010 on Windows Server 2008 (or R2) box, and if you follow the link provided by the wizard and download the general .Net Framework 3.5 from MS Downloads you are likely to get the error “You must use the Role Management Tool to install or configure Microsoft .Net Framework 3.5” upon installing it.

image

As the .Net Framework 3.5 is bundled in as a “feature” and you must add it from the Server Manager/Features snap-in (formerly add/remove programs). This should not be only pertinent to Exchange but would be applicable to all other apps that require .Net Framework 3.5)

image

PowerShell : How do I find all DCs in my forest ?

Standard

 

I find the –computerrole parameter of Get-QADComputer handy to find DCs and when usually I have to retrieve something from them with a WMI query, pipeline to (GWMI),  Here is a quick way to retrieve all DCs in a multi-domain forest model using the .NET namespace i.e [DirectoryServices.ActiveDirectory.Forest] method.

To find Global Catalogs only;

[DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest().GlobalCatalogs | ft name,OSVersion,Domain

To find all domain controllers;

[DirectoryServices.Activedirectory.Forest]::GetCurrentForest().domains | %{$_.domaincontrollers} | ft name,OSVersion,Domain

 

To find out what other information you can retrieve from the DCs via this method simply pipe to the Get-Member Cmdlet;

[DirectoryServices.Activedirectory.Forest]::GetCurrentForest().domains | %{$_.domaincontrollers} | Get-Member

 

image

PowerShell : How do I clear sIDhistory attribute ?

Standard

What is sIDhistory attribute ?

The sIDhistory attribute is the key attribute that holds the previous SID(s) of Users and Groups objects that facilitate the Active Directory migrations. It contains previous SIDs used for the object if the object was moved from another domain. Whenever an object is moved from one domain to another, a new SID is created and that new SID becomes the objectSID. The previous SID is added to the sIDHistory property. ADMT is one tool that allows you migrate SID from one domain to another, it calls on to the DsAddSidHistory API to accomplish this task.

However, there are times when you look into clearing the sIDhistory attribute after the migration is complete such as when you are attempting to avoid a token size bloat (kerberos token size threshold). You must do your homework before trying to remove sIDhistory, you should check the ACLs of your servers and applications and you should NOT clean up all groups (or users) at once, you should always try accessing the target resources and applications after sIDhistory has been cleared from a few groups/users, only after successful access (of a user that has re-authenticated – i.e. doesn’t have the SIDs from a group’s sIDhistory in his token), you should proceed with a mass removal.

To use PowerShell with Quest Cmdlets,

Get-QADUser user1 | %{Set-QADUser $_ -ObjectAttributes @{sIDHistory=@{delete=$_['sIDHistory']}}}

You may also pass a list of users or groups

Get-QADUser (get-content users.txt) | %{Set-QADUser $_ -ObjectAttributes @{sIDHistory=@{delete=$_['sIDHistory']}}}

PowerShell : How do I set the delegation sensitive flag on users and computers ?

Standard

Kerberos Delegation, constrained and unconstrained is a complex topic, and one that often comes up when Security implications of External/Forests Trusts are discussed. Few days ago, on ActiveDir a similar topic was shed light upon. In brief Brian Arkills sums it up below,

The other security implication that most folks seem oblivious to is the one that comes with unconstrained Kerberos delegation across a trust. When you’ve got a single domain/forest by itself, your domain admin group controls who/what can use delegation. Once you setup a trust to another domain, you extend that ability to the domain admins in the other domain(s). In other words, the domain admins in the other domain can choose to allow a user/computer in their domain to permit unconstrained Kerberos delegation using the user accounts in *your* domain. Almost everyone says unconstrained delegation is bad, and the assumption is that no one will use it. But there are no controls in the product to prevent its use, except by also preventing any delegation (i.e. by marking all or a subset of user accounts as ‘sensitive to delegation’). And of course, unconstrained delegation is the only way to use delegation across a forest trust meaning it’s the only game in town for certain scenarios.

A service that runs under an account that is trusted for Kerberos delegation can assume/impersonate the identity of a client requesting the service. This parameter sets the TrustedForDelegation property of an account object. This value also sets the ADS_UF_TRUSTED_FOR_DELEGATION flag of the Active Directory User Account Control attribute.

It is that marking of the user accounts as “delegation sensitive” with PowerShell is what I would like to share with you.

image

For user and computer accounts, as stated above the setting is enclosed under the useraccountcontrol bits.

http://support.microsoft.com/kb/305144

We take the TRUSTED_FOR_DELEGATION and its associated value in decimal i.e 524288 and assign it a variable.

$NOT_DELEGATED=1048576

Using Quest Cmdlets, we use the Set-QADUser and use the bitwise exclusive operator to set the flag as sensitive (Thanks to Shay Levy for helping me with the correct bitwise syntax)

Get-QADUser user1  |
    Set-QADObject $_ -ObjectAttributes @{userAccountControl= ($_.userAccountControl -bxor $NOT_DELEGATED)}

For computer accounts, there is an explicit parameter for the Set-QADComputer Cmdlet i.e -TrustForDelegation

With ADWS (the native AD Cmdlets) the same parameter (being applicable to both i.e users and computers) for Set-ADUser and Set-ADComputer is called –TrustedForDelegation.

By default, when an account has been granted delegation privileges *every* user account can be “impersonated” in this way. However, with above you can mark certain user accounts as “delegation sensitive”, which means that those user accounts can never be used in a delegation scenario. Marking admin accounts as delegation sensitive is highly recommended. Generally, delegation is used with Kerberos, but there is an option to use protocol transition so that NTLM might be used on some of the hops (this is called S4U). Also note that for service accounts (user accounts), the delegation tab will only appear (allowing for the constrained delegation) when there is a SPN registered against that user account.

image

More reading here :

http://blogs.technet.com/b/askds/archive/2008/03/06/kerberos-for-the-busy-admin.aspx

http://blogs.technet.com/b/askds/archive/2008/06/13/understanding-kerberos-double-hop.aspx

Can a KMS Server activate clients in multiple domains ?

Standard

Yes, the KMS client activation is supported in multi-domain environment in which the KMS host belongs to one domain and needs to cater to the clients in others.

For this to work, you need to create a ‘multi-string value’ registry key under “HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionSoftwareProtectionPlatform” called “DNSDomainPublishList” on your KMS Server.

image

When done, restart the “Software Protection” sppsvc service on your KMS host and watch for the Event ID 12294 log under application logs. You should one event for each domain you have asked KMS to publish itself in.

image

Additionally, under each domain you can use NSLookup to verify the _vlmcs SRV record.

nslookup -type=srv _vlmcs._tcp

KMS communication happens over TCP Port 1688, if the domains you have added are in other region and you would like to verify if clients can talk to your KMS host, then from a client on the other side use PortQry to ascertain that port is not being blocked

portqry –n FQDN_of_your_host –e 1688 –p both

If the environment does not support Dynamic DNS, then SRV Resource Records can be manually created to publish the KMS host.

The KMS SRV RR is created under TCP node of your DNS Domain.

image

On how to setup and configure KMS Server/host a Server Core, see my other post.

Other details can be found under Technet Library : http://technet.microsoft.com/en-us/library/ff793419.aspx

PowerShell : How to lookup Schema version of your forest ?

Standard

The schema version is revealed via the objectversion attribute off of the schema object from your configuration head of the forest i.e “cn=schema,cn=configuration,dc=yourdomain,dc=int”.

So using Quest Cmdlets, you can run this query :

Get-QADObject "cn=schema,cn=configuration,dc=yourdomain,dc=int" -ip objectversion | select objectversion

qadobject_sv

The –ip is the alias for includedproperties.

And, when using the native AD Cmdlets of Server 2008 R2 (ADWS), the syntax is slightly different ;

Get-ADObject "cn=schema,cn=configuration,dc=r2,dc=lab" -properties objectversion

qadobject_sv1

Above, you see the query ran with Quest Cmdlets resulting in objectversion 31 which is against a Server 2003 R2 Forest, whereas the latter is for a Server 2008 R2 Forest i.e Schema version 47.

Reviewing few very useful adds in Quest AD Cmdlets v1.4

Standard

Whereas most of newly added cmdlets focus on  PKI and Email Address Management in v1.4, there are a few cmdlets and handful of new parameters that ought to come in very handy with your AD tasks. Below I review a few that I think are some great adds :

When you are enumerating a large number of objects in shell (without outputting results into a file), you might just want to have a quick idea of the ‘total’ number of objects meeting the criteria of you query.

Get-QADProgressPolicy

“displays a progress bar for long-running commands”

progress_bar

This progress bar overlays (highlights in and out) as your query is running. It also appears when you are performing a count using the measure-object cmdlet or the “.count” switch

progress_bar2

You can set the progress bar setting and its threshold with

Set-QADProgressPolicy -ShowProgress $true -ProgressThreshold 2

The –activity parameter when relying on the progress bar allows you tag each line of progress with a number so that lengthy process is a bit more obvious with respect to the process to one or more cmdlet’s retrieved results.

Some new parameters :

Five new parameters for Get-QADUser

ExpiredFor

Inactive

InactiveFor

NotLoggedOnFor

PasswordNotChangedFor

Four new parameters for Get-QADComputer

Inactive

InactiveFor

NotLoggedOnFor

PasswordNotChangedFor

But what mechanism decides the “inactivity” benchmark to ask cmdlet to retrieve that information ?

You do.

Get-QADInactiveAccountsPolicy

inactivepolicy1

You can change these settings,

Set-QADInactiveAccountsPolicy -AccountExpiredPeriod 0 -AccountNotLoggedOnPeriod 30 –PasswordNotChangedPeriod 120

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Note : These settings are profile specific so ones you define these thresholds they will stay there until you change those settings again.

The NotLoggedOnPeriod is probably based on the LastLogonTimeStamp, but I will check and edit this post if its any different. If it is, remember it may not be accurate and should only be used for estimation. The LastLogonTimeStamp gets updated from the LastLogon (DC specific attribute) based on a 9-14 day swing period.

Also :

“This parameter overrides the logon-related inactivity condition of the Inactive or InactiveFor parameter. Thus, if the NotLoggedOnFor value of 60 is supplied in conjunction with the InactiveFor value of 30, the cmdlet searches for accounts that are expired for 30 or more days, or have the password age of 30 or more days, or have not been used to log on for 60 or more days.”

Previously if you had to use the Get-QADGroupMember cmdlet to retrieve the enabled accounts only, you had to pass the LDAPFilter, now you can use the same –enabled and –disabled parameter as you could with Get-QADUser cmdlet since v1.3.

groupmemberdisabled

This and much more. All details can be found here.

The folks who develop these cmdlets and work on adding new parameters do take the feedback very seriously. I have myself asked and gotten couple of requests met. You can do the same.