Debugging unattended domain join on Windows Azure VMs

Introduction

One great thing about Windows Azure PowerShell is the ability to join a VM to an Active Directory domain during provisioning, this ability is not available in the portal. Joining a domain during Windows setup is nothing new, and it is accomplished by using the normal Windows unattended setup mechanism; namely unattend.xml. In unattend.xml you can specify the following information about the domain you want to join and the account that has permissions to perform the join operation in the directory (excerpt has been edited for readability):

<component name="Microsoft-Windows-UnattendedJoin" processorArchitecture="amd64">
<Identification>
  <Credentials>
   <Domain><NetBIOS domain name></Domain>
   <Username><NT type (samaccountname) username></Username>
   <Password><password in encrypted form></Password>
  </Credentials>
  <JoinDomain><FQDN of domain to join></JoinDomain>
  <MachineObjectOU><DN of OU to place machine account in></MachineObjectOU>
</Identification>
</component>

You usually don’t create the unattend.xml file manually, but rather use a tool like Windows System Image Manager from the Windows Assessment and Deployment Kit (ADK).

I recently had an issue where none of my new VMs would join the domain during provisioning, leaving them all in a workgroup. That led me to compile the following during my debugging.

Add-WindowsProvisioningConfig

The cmdlet that enabled a Windows Azure VM to join a domain is called Add-WindowsProvisioningConfig. If used with the –WindowsDomain parameter it lets you specify these additional parameters:

Parameter Info
JoinDomain FQDN of domain to join
Domain NetBIOS name of account with permission to join computers to domain specified in the JoinDomain parameter. This is usually always the NetBIOS name of the domain from JoinDomin, but could be from another domain in the forest or a trusted domain.
DomainUserName NT-style username (samaccountname) of account with permissions to join the domain specified in JoinDomain
DomainPassword Password of the account with permissions to join the domain specified in JoinDomain
MachineObjectOU DN of OU where the computer account of the VM should be placed

This info is loaded into the unattend.xml file used to setup the new VM. After that the unattended setup process continues  as with any regular Windows install.

Logs

If domain join does not work there are several logs that should be examined.

Operation logs in the portal

Under Management Services in the Windows Azure portal you find the Operation Logs.

image

The provisioning of a new VM is an AddRole operation, first one with Status Started and then another one with Status Succeeded. By examining the details of these you can see what is passed to the back end. This is particularly useful if you are using scripts which pass variables to the domain join parameters. Here you see exactly what is passed. Note that the password is omitted from the logs, that is not an error.

Windows Setup logs

After the portal has done its job the rest of the provisioning is left to the normal Windows unattended setup process and is handled entirely within the VM. That means that any normal troubleshooting techniques for unattended Windows setup applies. The working folder of Windows Setup is C:\Windows\Panther. Here you will find the unattend.xml file used during setup (if is has not been deleted by setup itself, Azure does not do this), and the logs for the entire setup process:

File Info
unattend.xml The answer file for unattended Windows setup
setuperr.log Any major errors encountered during setup
setupact.log All setup activity

The first thing you should do is check unattend.xml and verify that it contains the correct info.

Domain join during unattended setup is done with the djoin.exe executable, so to debug domin join we need to search for that in setupact.log. Also searching for the words Warning or Error could reveal useful information. This is an excerpt from the setupact.log with the error I encountered:

2014-03-11 14:09:45, Info     [DJOIN.EXE] Unattended Join: Begin
2014-03-11 14:09:45, Info     [DJOIN.EXE] Unattended Join: Loading input parameters…
2014-03-11 14:09:45, Info     [DJOIN.EXE] Unattended Join: AccountData = [NULL]
2014-03-11 14:09:45, Info     [DJOIN.EXE] Unattended Join: UnsecureJoin = [NULL]
2014-03-11 14:09:45, Info     [DJOIN.EXE] Unattended Join: MachinePassword = [secret not logged]
2014-03-11 14:09:45, Info     [DJOIN.EXE] Unattended Join: JoinDomain = [corp.mydomain.com]
2014-03-11 14:09:45, Info     [DJOIN.EXE] Unattended Join: JoinWorkgroup = [NULL]
2014-03-11 14:09:45, Info     [DJOIN.EXE] Unattended Join: Domain = [corp]
2014-03-11 14:09:45, Info     [DJOIN.EXE] Unattended Join: Username = [Administrator]
2014-03-11 14:09:45, Info     [DJOIN.EXE] Unattended Join: Password = [secret not logged]
2014-03-11 14:09:45, Info     [DJOIN.EXE] Unattended Join: MachineObjectOU = [CN=Computers,DC=corp,DC=mydomain,DC=com]
2014-03-11 14:09:45, Info     [DJOIN.EXE] Unattended Join: DebugJoin = [NULL]
2014-03-11 14:09:45, Info     [DJOIN.EXE] Unattended Join: DebugJoinOnlyOnThisError = [NULL]
2014-03-11 14:09:45, Info     [DJOIN.EXE] Unattended Join: TimeoutPeriodInMinutes = [NULL]
2014-03-11 14:09:45, Info     [DJOIN.EXE] Unattended Join: Checking that auto start services have started.
2014-03-11 14:09:45, Info     [DJOIN.EXE] Unattended Join: Calling DsGetDcName for corp.mydomain.com…
2014-03-11 14:09:45, Info     [DJOIN.EXE] Unattended Join: DsGetDcName returned [dc2.corp.mydomain.com]
2014-03-11 14:09:45, Info     [DJOIN.EXE] Unattended Join: Constructed domain parameter [corp.mydomain.com\DC2.corp.mydomain.com]
2014-03-11 14:09:45, Warning     [DJOIN.EXE] Unattended Join: NetJoinDomain attempt failed: 0×2, will retry in 10 seconds…
2014-03-11 22:09:56, Warning     [DJOIN.EXE] Unattended Join: NetJoinDomain attempt failed: 0×2, will retry in 10 seconds…

As you can see from this case, the NetJoinDomain function fails and is eventually abandoned. You can also find these errors in the System log:

ID: 4097
Source: NetJoin
Info: The machine SERVER1 attempted to join the domain corp.mydomain.com\DC2.corp.mydomain.com but failed. The error code was 2.

To find out more about this we need to look at another log; C:\Windows\debug\NetSetup.log. This file contains information for alle domain join operations performed on a machine, not just the ones during setup. Here is a section from mine:

03/11/2014 22:24:44:407 NetpDoDomainJoin
03/11/2014 22:24:44:407 NetpMachineValidToJoin: ‘SERVER1′
03/11/2014 22:24:44:407     OS Version: 6.2
03/11/2014 22:24:44:407     Build number: 9200 (9200.win8_gdr.130531-1504)
03/11/2014 22:24:44:407     SKU: Windows Server 2012 Datacenter
03/11/2014 22:24:44:407     Architecture: 64-bit (AMD64)
03/11/2014 22:24:44:407 NetpDomainJoinLicensingCheck: ulLicenseValue=1, Status: 0×0
03/11/2014 22:24:44:407 NetpGetLsaPrimaryDomain: status: 0×0
03/11/2014 22:24:44:407 NetpMachineValidToJoin: status: 0×0
03/11/2014 22:24:44:407 NetpJoinDomain
03/11/2014 22:24:44:407     Machine: SERVER1
03/11/2014 22:24:44:407     Domain: corp.mydomain.com\DC2.corp.mydomain.com
03/11/2014 22:24:44:407     MachineAccountOU: CN=Computers,DC=corp,DC=mydomain,DC=com
03/11/2014 22:24:44:407     Account: corp\Administrator
03/11/2014 22:24:44:407     Options: 0×23
03/11/2014 22:24:44:407 NetpLoadParameters: loading registry parameters…
03/11/2014 22:24:44:407 NetpLoadParameters: DNSNameResolutionRequired not found, defaulting to ’1′ 0×2
03/11/2014 22:24:44:407 NetpLoadParameters: DomainCompatibilityMode not found, defaulting to ’0′ 0×2
03/11/2014 22:24:44:407 NetpLoadParameters: status: 0×2
03/11/2014 22:24:44:407 NetpDisableIDNEncoding: no domain dns available – IDN encoding will NOT be disabled
03/11/2014 22:24:44:407 NetpJoinDomainOnDs: NetpDisableIDNEncoding returned: 0×0
03/11/2014 22:24:44:407 NetpJoinDomainOnDs: status of connecting to dc ‘\\DC2.corp.mydomain.com’: 0×0
03/11/2014 22:24:44:407 NetpJoinDomainOnDs: Passed DC ‘DC2.corp.mydomain.com’ verified as DNS name ‘\\DC2.corp.mydomain.com’
03/11/2014 22:24:44:407 NetpLoadParameters: loading registry parameters…
03/11/2014 22:24:44:407 NetpLoadParameters: DNSNameResolutionRequired not found, defaulting to ’1′ 0×2
03/11/2014 22:24:44:407 NetpLoadParameters: DomainCompatibilityMode not found, defaulting to ’0′ 0×2
03/11/2014 22:24:44:407 NetpLoadParameters: status: 0×2
03/11/2014 22:24:44:407 NetpDsGetDcName: status of verifying DNS A record name resolution for ‘DC2.corp.mydomain.com’: 0×0
03/11/2014 22:24:44:407 NetpProvisionComputerAccount:
03/11/2014 22:24:44:407     lpDomain: corp.mydomain.com
03/11/2014 22:24:44:407     lpMachineName: SERVER1
03/11/2014 22:24:44:407     lpMachineAccountOU: CN=Computers,DC=corp,DC=mydomain,DC=com
03/11/2014 22:24:44:407     lpDcName: DC2.corp.mydomain.com
03/11/2014 22:24:44:407     lpDnsHostName: (NULL)
03/11/2014 22:24:44:407     lpMachinePassword: (null)
03/11/2014 22:24:44:407     lpAccount: corp\Administrator
03/11/2014 22:24:44:407     lpPassword: (non-null)
03/11/2014 22:24:44:407     dwJoinOptions: 0×23
03/11/2014 22:24:44:407     dwOptions: 0×40000003
03/11/2014 22:24:44:407 NetpLdapBind: Verified minimum encryption strength on DC2.corp.mydomain.com: 0×0
03/11/2014 22:24:44:407 NetpLdapGetLsaPrimaryDomain: reading domain data
03/11/2014 22:24:44:407 NetpGetNCData: Reading NC data
03/11/2014 22:24:44:407 NetpGetDomainData: Lookup domain data for: DC=corp,DC=mydomain,DC=com
03/11/2014 22:24:44:407 NetpGetDomainData: Lookup crossref data for: CN=Partitions,CN=Configuration,DC=corp,DC=mydomain,DC=com
03/11/2014 22:24:44:423 NetpLdapGetLsaPrimaryDomain: result of retrieving domain data: 0×0
03/11/2014 22:24:44:423 NetpCheckForDomainSIDCollision: returning 0×0(0).
03/11/2014 22:24:44:423 NetpGetDnsHostName: PrimaryDnsSuffix defaulted to DNS domain name: corp.mydomain.com
03/11/2014 22:24:44:423 NetpGetComputerObjectDn: Cracking DNS domain name corp.mydomain.com/ into Netbios on \\DC2.corp.mydomain.com
03/11/2014 22:24:44:423 NetpGetComputerObjectDn: Crack results:     name = corp\
03/11/2014 22:24:44:423 NetpGetComputerObjectDn: Cracking account name corp\SERVER1$ on \\DC2.corp.mydomain.com
03/11/2014 22:24:44:423 NetpGetComputerObjectDn: Crack results:     Account does not exist
03/11/2014 22:24:44:423 NetpGetComputerObjectDn: Specified path ‘CN=Computers,DC=corp,DC=mydomain,DC=com’ is not an OU
03/11/2014 22:24:44:423 NetpCreateComputerObjectInDs: NetpGetComputerObjectDn failed: 0×2
03/11/2014 22:24:44:423 NetpProvisionComputerAccount: LDAP creation failed: 0×2
03/11/2014 22:24:44:423 NetpProvisionComputerAccount: Cannot retry downlevel, specifying OU is not supported
03/11/2014 22:24:44:423 ldap_unbind status: 0×0
03/11/2014 22:24:44:423 NetpJoinCreatePackagePart: status:0×2.
03/11/2014 22:24:44:423 NetpAddProvisioningPackagePart: status:0×2.
03/11/2014 22:24:44:423 NetpJoinDomainOnDs: Function exits with status of: 0×2
03/11/2014 22:24:44:423 NetpJoinDomainOnDs: status of disconnecting from ‘\\DC2.corp.mydomain.com’: 0×0
03/11/2014 22:24:44:423 NetpJoinDomainOnDs: NetpResetIDNEncoding on ‘(null)’: 0×0
03/11/2014 22:24:44:423 NetpDoDomainJoin: status: 0×2

I have highlighted my particular error. As you can see I specified the DN of the computers container as the location of the new computer object. Since Computers is in fact a container and not an OU, the NetpCreateComputerObjectInDs function fails. After I specified a bona fide OU in my Add-WindowsAzureProvisioningConfig cmdlet the VM was successfully joined to my domain. If you actually want the computer object to be placed in the Computers container just omit the MachineObjectOU parameter from Add-WindowsAzureProvisioningConfig. Since the Computers container is the default location for new computer objects, unless redirected by the admin or overridden, your VMs account will end up there.

Will it run? How to run your favorite legacy OS in a Windows Azure VM

Introduction

Old OSs are very popular, at least judging by the number of, for want of a better word, “legacy” servers I find in customer data centers. The old workhorses Windows Server 2003/2003 R2, Windows 2000 and even good old Windows NT pop up in disturbing numbers. With them, the question “Will Windows X, run in a Windows Azure VM?” often follows. To be able to answer that question we first need to talk about “run” vs. “supported”. A lot of OSs can be made to run in a Windows Azure VM, but that does not mean that Microsoft will support that OS. Unfortunately a lot of people are only interested in the “run” part of the equation, ignoring any problems of supportability down the road. Support is very straight forward; the oldest supported Windows OS running in a Windows Azure VM is Windows Server 2008 R2 x64, as stated in KB2721672: Microsoft server software support for Windows Azure Virtual Machines. So if you want support the buck stops there. But what can we make to run if we throw supportability to the wind…

It’s still Hyper-V

All the physical servers in a Windows Azure data center run a modified version of Windows Server with the Hyper-V role installed. So basically all the capabilities of Hyper-V should be available in Windows Azure, unless they have been specifically blocked. The About Virtual Machines and Guest Operating Systems page lists all the guest operating systems that are supported on Hyper-V, so lets assume that we can run all of those. I’m not going to test all the OSs on that list, but rather focus on some specific golden oldies (all 32-bit editions):

  • Windows 2000
  • Windows XP
  • Windows Server 2003

There is also a lot of rumor on the Internet concerning support for 32-bit (x86) VMs in Windows Azure. Although all the images in the gallery and the fact that the earliest supported server OS (Windows Server 2008 R2) is only available in 64-bit (x64), this is never actually stated anywhere officially. (At least not that I have found.)

Another area where there is a lot of talk is concerning client operating systems in Windows Azure VMs. In this case Microsoft is very clear; client OSs are not supported and it is a violation of the license to install and run one in a Windows Azure VM. For the sake of scientific discovery I will ignore that issue for this post.

So lets see what’s what…

Basic requirements

I’m going to work from these premises during my testing:

  • The legacy OS needs to be on the supported list for Hyper-V
  • Hyper-V Integration Components need to be available
    Either on the vmguest.iso image, already in the OS or available for download.
  • Remote Desktop for Windows VMs and SSH for Linux VMs must be available
  • Only VHD images are supported in Windows Azure, not VHDX
  • None of the selected legacy OSs will support being generalized in a way that Windows Azure can use, so we can only upload OS disks, not images. (Windows Azure uses the setup technology introduced in Windows Vista, codenamed Panther, which legacy OSs don’t.)

Basic steps

Here is what we need to do (at least):

  1. Use a Hyper-V host running Windows Server 2012 R2
    This probably not a requirement, but the latest and greatest is always nice.
  2. Install a VM with the legacy OS, must select Generation 1 and the VHD disk format.
  3. Once OS install completes, install the Hyper-V integration components
  4. Update the OS through e.g. Microsoft Update
    Having the latest updates will maximize the chance of success
  5. If you want remote PowerShell or WinRM make sure to install those optional updates.
  6. Enable Remote Desktop and make sure the Remote Desktop exception is enabled in the Windows Firewall if it is enabled.
  7. If you are using WinRM technology configure that, preferably with HTTPS instead of HTTP, and enable the appropriate firewall exceptions.
  8. If you are actually trying to run a production server with a legacy OS in Windows Azure (something you should not do), remove any special drivers or low level software that might break the VM. You can always install this alter.
  9. Shut down the VM on your Hyper-V Server
  10. Upload the VHD to a Windows Azure storage account (Add-AzureVHD)
  11. Register the new blob as an OS image (Add-AzureDisk)
  12. Start the VM in Azure and log on (hopefully).

The results

Using the above method I was able to obtain these results:

OS Runs Notes
Windows 2000 Yes
  • Professional, Server and Advanced Server all share the same code base and all work
  • Windows Server 2012 removed Windows 2000 support from the Integration components so you have to use integrations components from Windows Server 2008 R2.
  • Performance was not great on my VM…
Windows XP x86 Yes  
Windows Server 2003 x86 Yes Windows Server 2003 R2 is pretty much the same code base so it should run fine too. And in fact it does.

I assume that Windows Server 2003/2003R2 and XP x64 will also work.

Feel free to try some golden oldies yourself and use the comments for your results. Good luck.

Microsoft Product Use Rights (PUR) document update; great news for Windows Azure and hosters

What is Product use Rights (PUR)?

from microsoft.com:

“When you purchase a software license through a Microsoft Volume Licensing program, the terms and conditions for how you can use the software are defined in the Volume Licensing Product Use Rights (PUR) document, Product List document, and program agreement. The PUR is updated quarterly.”

The change

Effective January 1 2014 Microsoft made a pretty significant change to the Software Assurance benefit. This is from the Windows Server 2012 R2 Remote Desktop Service Licensing Data Sheet:

RDS User CALs Extended Rights through Software Assurance
Today, RDS CALs permit remote access to the Windows Server GUI (Graphical User Interface) running on a customer’s on-premise server and RDS SALs (Subscriber Access License) if running on a shared-server environment. Effective January 1 2014, RDS User CALs will have Extended Rights through Software Assurance. In addition to the on-premise access, RDS User CAL customers will also be able to access the Windows Server GUI running on Windows Azure or on a third party’s shared server, without acquiring a separate RDS SAL.

To leverage this benefit customers should meet following requirements:

  • Maintain Software Assurance coverage on the RDS User CALs
  • Use dedicated VOSE (Virtual Operating System Environment) in Windows Azure or third party’s
    shared servers
  • Access Windows Server session-based desktops and/or applications running on shared server
    environments
  • Limit access by internal users only i.e. by company employees, vendors and contractors and not by
    external users such as customers
  • Assign each on-premise RDS User CAL to the same named user on Windows Azure or a third party’s
    shared servers
  • This RDS User CAL Software Assurance benefit allows each User to access RDS functionality only on one shared server environment (i.e. Windows Azure or a third party server) in addition to access the respective on premise servers. The customer must acquire extra RDS SALs (Subscriber Access License) if the same User needs to access RDS functionality on additional shared server environments.

This is indeed great news for all customers wanting to access a remote Windows Server Desktop in Windows Azure or at another third party hoster.

More info:

Quickly stop and start your Windows Azure lab

Introduction

I needed  way to easily stop and start my different lab setups in Windows Azure. I don’t want to keep running, and pay for, a set of VMs I use maybe once a month. So here is a PowerShell script to stop and start a set of Azure VMs. One important dimension here is the order in which the VMs start (and possibly; shuts down, depending on your setup). Since all IP addresses are dynamically allocated in Windows Azure I had to make sure that my VMs started in a specific order and that the script executed synchronously. That way whatever IP they had when they were provisioned would most likely be assigned to them when they started. Therefore the script includes code to start and stop VMs in the order you specify them in the input file. It also tries to wait until the current VM is fully started or stopped before proceeding with the next one.

Pre-requisites, input file and usage

The input file is really simple. It is a text file with a Cloud Service name and a VM name on each line, separated by a semi-colon, no header:

<cs name>;<vm name>

The VMs in the file will be started in the order they are listed and stopped in the reverse order!

By default, the script looks for a txt file in its execution directory called Control-AzureVMs.txt. If it is not found PowerShell throws an error. You can override this behavior by specifying your own file with VMs to either start or stop.

You must already have your machine configured to use Windows Azure PowerShell and specify your subscription in the script:

Select-AzureSubscription “<your subscription name here>”

Whether you want to start or stop a set of VMs is controlled by a script parameter. You use either Stop or Start. Optionally you can add your own txt file with VMs after the Start/Stop parameter.

Usage with the default input file:

Control-AzureVMs.ps1 Stop

Control-AzureVMs.ps1 Start

Usage with the custom input file:

Control-AzureVMs.ps1 Stop MySetOfVms.txt

The code

Here is the code. I can think of all sorts of improvements, but I needed this quickly so that will have to wait. Error checking is pretty much non-existent at this point so use at your own risk. I accept no responsibility whatsoever.

UPDATE: With the release of the Windows Azure PowerShell module v0.7.3 you can now create DHCP reservations for your VMs that will persist when the machine is deallocated. Check out Get-AzureStaticVNetIP, Set-AzureStaticVNetIP, Remove-AzureStaticVNetIP and Test-AzureStaticVNetIP.

NIC 2014 Slide deck

Here is my slide deck from the Nordic Infrastructure Conference (NIC) 2014. My talk was called Modern authentication for the Cloud Era and covered claims based authentication and some common scenarios, OAuth and OpenID Connect. Thanks to everyone who attended my session. Hope to see you there next year!

http://www.slideshare.net/MorganSimonsen/nic-2014-modern-authentication-for-the-cloud-era

Delegating computer object management tasks

Introduction

The subject of delegating permissions in Active Directory for management of computer objects has been covered many times in many forums. I wanted to try to collect all that information as well as add some refinements of my own.

Rights vs. permissions

In the olden days, back when I was just a wee lad and Windows NT was new, the ability to join a computer to a domain was controller by a user right called Add workstations to domain. This user right is only valid on domain controllers. Any use who had this right could join computers to a Windows NT domain. The user right still exists and is in use even on Windows Server 2012 R2 Domain Controllers running Active Directory domains. When users join their computers to the domain using their own credentials they do it using this user right. It is, in fact, the only option available to them, since no regular users are granted any permissions over computer objects in Active Directory by default.

Back in the NT era this right was granted to the Users group and there was no limit to how many computers any give user could add to the domain. When Windows 2000 came along and with it Active Directory the user right was changed to apply to the Authenticated Users security principal and any one user could only add 10 computers to a domain by default. But the preferred way for Active Directory was to use permissions in the directory service to control object creation, modification and deletion…

Active Directory has a very fine grained permissions set allowing you to set permissions for objects as well as their properties. These permissions work the same way as the rest of the authorization model in Windows does by using Access Control Lists (ACL) with security principals and their permissions listed in individual Access Control Entries (ACE). Permissions can be granted anywhere in the hierarchy and inherited down to objects and containers. Granting permissions in Active Directory to someone or something is often called delegation. Computer objects are of course also included in these permissions and we can create much better delegation of control than we could with just a global user right.

We’ll cover three delegation of control scenarios regarding computer object management in this post:

  1. Allowing a security principal to join (add) a computer to a domain
  2. Allowing a security principal to join and re-join a computer to a domain
  3. Allowing a security principal to rename a computer in a domain
  4. Allowing a security principal to move computer objects in a domain

You can of course combine any of these.

Creating a computer object and changing its properties is what is required to join a computer to the domain. The container could be the Computers container or any other OU or container, including the domain itself but I do not recommend that.

When a computer joins an Active Directory domain without specifying a path, it is placed in the Computers container. The Computers container is not an OU and so it cannot have Group Policy Objects linked to it or have sub containers or OUs. If you are fine with all computer objects being created in this container you can delegate the permissions below to the Computers container

1. Allowing a security principal to join (add) a computer to a domain

First out is the most common scenario; join a computer to an Active Directory domain. As stated earlier it is not necessary to delegate this to regular users since the very few cases where they join their own computers to a domain should be covered by the Add workstation to domain user right. One exception to this is if you want to tighten down security and remove all security principals from this user right. In that case, if you still want to allow regular users to be able to join computers to a domain you have to delegate permissions to them. The more common case is that whatever deployment solution you use adds the computers to the domain. This is by far the best solution since very few users have any idea what a domain is.

A best practice is to create a service account used only for adding computers to the domain. This account should be clearly labeled, have a strong password and not have any other rights or permissions in you directory except the ability to join the domain. That being said the procedure below works for any security principal you want to delegate permissions to join the domain for.

  1. Identify the security principal that you want to delegate permissions for
    This can be any security principal; user, group etc.
  2. Identify the container or OU where you want to allow users to manipulate computer objects
  3. Right click the container or OU you selected and select Delegate Control…
    image
  4. The Delegation of Control Wizard opens, hit Next
    image
  5. The Users or Groups window opens:
    Select the security principal you want to grant permissions to, then hit Next again.
    image
  6. The Tasks to Delegate window opens:
    Select Create a custom task to delegate and hit Next
    image
  7. The Active Directory Object Type window opens:
    Select Only the following objects in the folder and select Computer objects, select Create selected objects in this folder and finally hit Next
    image
  8. The Permissions window opens
    Select Property-specific and select Read All Properties. This is actually redundant since this permissions are already granted to the Authenticated Users principal, but the delegation of control wizard will not let you continue without selecting something on this screen.image
  9. Finally the Completing the Delegation of Control Wizard window opens showing you a summary of your actions. Hit Finish.
    image

    Delegation of Control Wizard Summary

You chose to delegate control of objects
in the following Active Directory folder:

    saferoad.com/Computers

The groups, users, or computers to which you
have given control are:

    Domain Join Account (SvcJoinComputerToDom@saferoad.com)

They have the following permissions:

    Read All Properties

For the following object types:

    Computer

    The selected principals can now join computers to the domain.

2. Allowing a security principal to join and re-join a computer to a domain

    The second scenario; allowing a principal to also re-join a computer to a domain requires some additional permissions. This is useful if you want to have a service account that can manage all computer accounts, also existing ones. System Center Configuration Manager for example requires these permissions.

  1. Identify the security principal that you want to delegate permissions for
  2. Identify the container or OU where you want to allow users to create and configure computer objects
  3. Right click the container or OU you selected and select Delegate Control…
    image
  4. The Delegation of Control Wizard opens, hit Next
    image
  5. The Users or Groups window opens:
    Select the security principal you want to grant permissions to, then hit Next again.
    image
  6. The Tasks to Delegate window opens:
    Select Create a custom task to delegate and hit Next
    image
  7. The Active Directory Object Type window opens:
    Select Only the following objects in the folder and select Computer objects, select Create selected objects in this folder and Delete selected objects in this folder, and finally hit Next
    image
  8. The Permissions window opens
    Select Property-specific and select these individual permissions:
    - Reset Password
    - Read and write Account Restrictions
    - Validated write to DNS host name
    - Validated write to service principal name
     
    image
  9. Finally the Completing the Delegation of Control Wizard window opens showing you a summary of your actions. Hit Finish.
    image

      Delegation of Control Wizard Summary

    You chose to delegate control of objects
    in the following Active Directory folder:

    <domain>/Computers

The groups, users, or computers to which you
have given control are:

    Domain Join Account (SvcJoinComputerToDom@<domain>)

They have the following permissions:

    Reset password
    Read and write account restrictions
    Validated write to DNS host name
    Validated write to service principal name

For the following object types:

    Computer

    The selected principals can now join computers to the domain as well as re-join computers when the computer account already exists.

3. Allowing a security principal to rename a computer in a domain

Here goes no. 3…

 
  1. Identify the security principal that you want to delegate permissions for
  2. Identify the container or OU where you want to allow users to create and configure computer objects
  3. Right click the container or OU you selected and select Delegate Control…
    image
  4. The Delegation of Control Wizard opens, hit Next
    image
  5. The Users or Groups window opens:
    Select the security principal you want to grant permissions to, then hit Next again.
    image
  6. The Tasks to Delegate window opens:
    Select Create a custom task to delegate and hit Next
    image
  7. The Active Directory Object Type window opens:
    Select Only the following objects in the folder and select Computer objects and hit Next 
    image
  8. The Permissions window opens
    Select Property-specific and select Write All Properties.
    Scroll down an add these individual permissions as well:
    - Validated write to DNS host name
    - Validated write to service principal name
     
    image
  9. Finally the Completing the Delegation of Control Wizard window opens showing you a summary of your actions. Hit Finish.
    image
    1. Delegation of Control Wizard Summary

    You chose to delegate control of objects
    in the following Active Directory folder:

        saferoad.com/Computers

    The groups, users, or computers to which you
    have given control are:

        Domain Join Account (SvcJoinComputerToDom@saferoad.com)

    They have the following permissions:

        Write All Properties
        Validated write to DNS host name
        Validated write to service principal name

    For the following object types:

        Computer

    The selected principals can now rename a computer in a domain.

4. Allowing a security principal to move computer objects in a domain

    The last one is a little more involved as it requires changing permissions on both the source container/OU and the destination. The destination container/OU requires the same permissions as in scenario 1 so set those. Follow these steps to configure the source container/OU:

    1. Identify the security principal that you want to delegate permissions for
    2. Identify the container or OU where you want to allow users to create and configure computer objects
    3. Right click the container or OU you selected and select Delegate Control…
      image
    4. The Delegation of Control Wizard opens, hit Next
      image
    5. The Users or Groups window opens:
      Select the security principal you want to grant permissions to, then hit Next again.
      image
    6. The Tasks to Delegate window opens:
      Select Create a custom task to delegate and hit Next
      image
    7. The Active Directory Object Type window opens:
      Select Only the following objects in the folder, select Computer objects and , select Delete selected objects in this folders, hit Next 
      image
    8. The Permissions window opens
      Select Property-specific and select Write All Properties
      image
    9. Finally the Completing the Delegation of Control Wizard window opens showing you a summary of your actions. Hit Finish.
      image

        Delegation of Control Wizard Summary

      You chose to delegate control of objects
      in the following Active Directory folder:

          saferoad.com/Computers

      The groups, users, or computers to which you
      have given control are:

          Domain Join Account (SvcJoinComputerToDom@saferoad.com)

      They have the following permissions:

          Write All Properties

      For the following object types:

          Computer

    More information

    There is an interesting distinction between joining a domain by exercising the user right Add workstation to the domain and using delegated permissions. If you join by the user right the owner of the resulting computer object is the Domain Administrators group, but if you join by delegated permissions the owner is the user who actually performed the join. Also if a principal has both the user right and delegated permissions, delegated permissions take precedent and are used to join the computer to the domain. A recommended best practice her would be to remove all principals from the user right and just rely on permissions. You do that by applying a policy to your domain controllers where no principal has the user right:

    image

    The location of the user right is:

    Computer Configuration\Policies\Windows Settings\Security Settings\Local Policies\User Rights Assignment

    You could also increase the default quota of 10 computer accounts added to the domain per user, but I do not recommend that. I essence you are copying the settings from Windows NT to your Active Directory domain and do not take advanced of the advanced delegation model in Active Directory. For completion here is how to change the quota:

    From any editor capable of displaying and changing individual attributes of Active Directory objects; display the properties of the domain NC. Locate the ms-DS-MachineAccountQuota property and change it to your desired value:

    image

    Links

    Here are a few links for further info:

    SQL Tips for novices

    Before you ask, I definitely count myself as a novice when it comes to SQL. Nevertheless, here are a few SQL tips I have picked up along the way…

    Enable SQL to communicate through the Windows Firewall

    SQL Database
    netsh advfirewall firewall add rule name=SQLPort dir=in protocol=tcp action=allow localport=1433 remoteip=localsubnet profile=DOMAIN
    SQL Browser
    netsh advfirewall firewall add rule name=SQLBrowser dir=in protocol=udp action=allow localport=1434 remoteip=localsubnet profile=DOMAIN
    SQL Server executable
    netsh advfirewall firewall add rule name="SQLExe(<SQL Instance name>)" dir=in action=allow program= "c:\Program Files\Microsof
    t SQL Server\MSSQL10_50.<SQL Instance name>\MSSQL\Binn\sqlservr.exe" remoteip=localsubnet profile=DOMAIN

    Reference:

    Make the local Administrators group SQL Admin

    It is very useful to have the local Administrators group on a SQL server be SQL Admin. Useful, not necessarily secure or a best practice. To be able to perform these steps you need access to an account that already is an SQL Admin of the server/instance you are trying to change.

    1. Open SQL Server Management Studio and log on
      To use Windows Integrated authentication you need to be logged onto the SQL server computer with an account that is already a SQL Admin, it using SQL authentication; just enter the username and password.
    2. Expand Security\Logins
    3. Right click and select New Login…
    4. In the Login name field enter BUILTIN\Administrators.
      For some reason SQL requires that all built in security principals be prefixed with the word BUILTIN instead of the computername.
    5. Select Server Roles and select serveradmin and sysadmin, leave any existing boxes ticked.
    6. Hit OK
    7. Exit SQL Server Management Studio, log off the computer, log on again with a user that is a member of the local Administrators group and open SQL Server Management Studio again. This time use Windows Authentication.
      Same thing in Transact-SQL:

    CREATE LOGIN "BUILTIN\Administrators" FROM WINDOWS;
    GO

    EXEC master..sp_addsrvrolemember @loginame = N’BUILTIN\Administrators’, @rolename = N’sysadmin’
    GO

    If you still cannot get access; make sure you are not running with User Account Control (UAC) enabled. UAC strips the Administrators group from your security token.

    Reference:

    Test connectivity to a SQL Server

    This is pretty cool…

    Create an empty file anywhere in the file system called test.udl.

    PowerShell: New-Item test.udl –type file

    Double click to open it. You will see the following dialogue box:

    image
    Enter the servername, select security mode and database, and hit Test Connection.

    Reference:

    Windows Azure

    Reference:

    Go DBAs! Smile

    Recommendations for LDAP lookup accounts and connections in Active Directory

    Introduction

    From time to time someone may want to access your Active Directory Directory Service with LDAP. Usually from a system or location that you view as unsecure or untrustworthy. Examples are printers that do directory lookups to send scanned documents by e-mail and external systems where a provider needs information about your users to provide them service. The querying party is often an open source implementation of an LDAP client. Here is some advice about how to configure such a setup.

    Connecting

    All Active Directory Domain Controllers provide LDAP over TCP and UDP ports 389, and Secure LDAP (LDAP-S) over TCP port 636, by default. If there is a firewall between your Domain Controller and the connecting system you will have to allow and/or forward the required ports. For any connection you should always use LDAP-S, especially for connections that traverse untrusted networks, e.g. the Internet. For recent versions of Windows Server the host firewall is enabled by default and the inbound rules for LDAP and LDAP-S are automatically enabled when the server is promoted to a domain controller. Depending on your network firewalls you may have to enable Allow edge traversal. You do this from the properties of the rule in the Windows Firewall with Advanced Security console:

    image

    Selecting a DC

    Choosing which DC the LDAP client connects to is either configured by you or located automatically. A Windows machine that is a member of a domain knows how to find LDAP servers in its domain, which it does by querying DNS. A lot of Active Directory discovery is done by DNS in Windows. A Windows client will typically query DNS for A (host) records for its own domain to find which servers are writable LDAP servers. All RW DCs register an A record for the domain name to indicate they are LDAP servers. Alternatively a Windows client can also query for SRV (service) records for _ldap._tcp.dc._msdcs.<DNS domain name>. The DC Locator component, implemented by the NETLOGON service on a Windows machine performs these queries. When a Windows client wants to log on to a domain it uses SRV records. But the fact that a Windows machine that is joined to a domain can find LDAP servers by using DNS does not mean that an application running on it can do the same, or take advantage of the information found by the DC Locator component. Very often an application that uses LDAP implements its own LDAP configuration and service discovery. Typically LDAP servers are either found by querying DNS for either A, CNAME, TXT or SRV records as specified by you, or LDAP servers a statically configured. If the connecting system is on your internal network then the best option would be for it to use DNS to discover LDAP servers based on the DNS name of the domain. That way the system will continue to function even if you introduce new or retire old domain controllers. If that is not possible try using an A record as an alias; like ldap.<DNS domain name>. The you can statically configure your LDAP client to connect to that name. If any change occurs in your directory service, all you have to do is update the alias. You can even have more than one record for the same alias and DNS will serve them up randomly. If the connecting system is outside your network and does not have access to your internal DNS zones, you are left with statically configuring it using either an IP address or an FQDN which is resolvable outside of your network.

    Some more info:

    Certificates

    The domain controller needs a certificate to be able to supply LDAP-S. You can in theory use a certificate signed by any authority, including a self signed one, as long as the connecting party either trust the signer or ignores certificate errors. The following KB article goes into details about the specific LDAP certificate requirements for domain controllers:

    It is not possible to configure a specific certificate for LDAP if there are several to choose from. The aforementioned KB article explains the certificate selection process that the DC uses.

    It is also a good idea to provide the connecting party with a base DN from which to start a search, although you cannot stop them from changing it.

    Account

    After the connection is established the connecting party needs to authenticate to access the directory. The most common form of authentication in this scenario is a username and password combination. Since Active Directory is its own authentication provider you will need to create an account in AD and provide the connecting party with the domain, username and password information. This account will be an implicit member of the Authenticated Users group when it is logged on and thus have the same access rights in the directory as the Authenticated Users principal has. Unless you have changed your directory considerably Authenticated Users will have read access to most of your Active Directory. Changing this is not a trivial task and would require you to change the very basic authorization settings of your directory, and since these settings are enforced on a schedule by the DS you will have to create your own way of making them stay changed.

    Any user account you opt to use will also be a member of the Domain Users group. This grants it certain rights in your domain that you might not want such an account to have. For example a member of Domain Users can log on to computers in your domain by power of the fact that Domain Users is a member of the Users group on every member computer in the domain. I recommend creating a new global security group, called NO_PRIVILEGE for example, and add the account to that group, and at the same time removing the account from Domain Users. By doing this you will revoke any permissions Domain Users has from the account. You cannot just remove it from Domain Users, since every user account in Active Directory must have a primary group associated with it. The NO_PRIVILEGE group will  become that new primary group once Domain Users membership is revoked.

    Testing

    To test if your setup work I recommend an LDAP browser or explorer. Windows includes one called LDP.EXE and it is quite good, but since it cannot ignore certificate errors, it might not work in all scenarios. Here are a couple of alternatives:

    I find that LDAP Admin servers all my needs. It even alerts you to certificate errors and lets you view the certificate and continue if you so choose.

    To test if the required ports are open and forwarded you can also use the PortQry utility from Microsoft. Here is an example command to check for LDAP-S:

    .\PortQry.exe –n <my DC FQDN> -p TCP -e 636

    Tip

    To ignore certificate errors in LDAP on open source systems I recommend doing a search for TLS_REQCERT and LDAPTLS_REQCERT.

    Bug in Windows Azure PowerShell module v 0.7.0

    The latest version of the Windows Azure PowerShell module v 0.7.0 (released 21-10-2013), which features such great improvements as Windows Azure Active Directory logon support, unfortunately has a bug relating to endpoint ACLs.

    Any Set-AzureEndpoint or Add-AzureEndpoint command which includes the ACL parameter will seem to succeed, but no ACL changes will be applied to the endpoint. I reverted to the previous release, v 0.6.16.1, and it works correctly.

    I submitted an issue on GitHub, hopefully it will be resolved soon.

    Troubleshooting ISO file sharing in System Center Virtual Machine Manager 2012 SP1

    So I was trying to use sharing of ISO files instead of copying when mounting on virtual machines. The really helpful dialog box in System Center Virtual Machine Manager (SCVMM) 2012 SP1 politely informs you that

    image

    OK, so what configuration?

    I found these steps for VMM 2008: How to Enable Shared ISO Images for Hyper-V Virtual Machines in VMM

    In short this is what you have to do:

    • Use a domain account as the VMM service account
    • Grant share and NTFS Read permissions to the VMM library shares that contain ISO files for both the VMM service account and the computer accounts of any Hyper-V hosts that need to access those ISO files
    • Configure constrained delegation for each Hyper-V host to allow delegation of credentials to the VMM library servers
    • Add the Hyper-V hosts to the Windows Autorization Access builtin group

    If you use a group to grant access to you Hyper-V hosts to the library share, like I did you have to restart them to update their security tokens. Configuring constrained delegation also requires a restart.

    But it wasn’t working! VMM just told med “Update failed” each time I tried to mount an ISO on a VM. This is the error I got:

    Error (12700)
    VMM cannot complete the host operation on the <Hyper-V host> server because of the error: ‘<VM>’ failed to add device ‘Virtual CD/DVD Disk’. (Virtual machine ID <GUID>)

    ‘<VM>’: User Account does not have sufficient privilege to open attachment ‘\\<VMM Library server>\MSSCVMMLibrary\ISOs\<ISO file>’. Error: ‘General access denied error’ (0×80070005). (Virtual machine ID <GUID>)
    Unknown error (0×8001)

    Recommended Action
    Resolve the host issue and then try the operation again.

    The Internet didn’t know why it didn’t work either. I know because I asked it!

    As far as I cloud see my permissions were correct so I had to figure out if there was another account involved. The best way I know to do that is by auditing object access. So first I enabled auditing of object access on my VMM Library server:

    image

    Next, to catch all security principals trying to access the files in the VMM Library, I added audit System Access Control List entries for both Authenticated Users and Everyone:

    image

    After setting this up I tried mounting the ISO again and then opened the Security Event Log. The first event of interest was a logon event (Event ID 4624):

    image

    The account listed here is the Run As account I use for Hyper-V host management. This was an Audit Success event since the account was allowed to log on to the VMM library server.

    Next was an attempt to access a share (Event ID 5140):

    image

    Again it was the RunAs account this time trying to access the VMM Library share with read permissions (ReadData or ListDirectory). Again, this was an Audit Success event since this was just a request for access. This was followed by something called a detailed file share (Event ID 5145):

    image

    This was our first Audit Failure event. This event is the result of the File Share request in the previous event. As you can see it was not successful. For the user this will result in an access denied message; exactly what I was seeing in the VMM console.

    So apparently the RunAs account is also involved in accessing the share. To test to see if this was the solution I added the RunAs account to the share and NTFS permissions with Read access. Immediately it was successful and the VM could access the ISO file directly from the VMM Library.

    Happy that I made it work I was still interested in knowing why the RunAs account was used for this. The answer was to be found in the VMM Add Resource Wizard. This is the wizard used to add fabric resources to VMM, like Hyper-V hosts or clusters. On the Credentials page we see this:

    image

    So the RunAs account is stored and used to access the hosts discovered with the wizard. The universe was once again in balance.

    Follow

    Get every new post delivered to your Inbox.

    Join 150 other followers