Tuesday, March 26, 2013

Azure Powershell Setup and IaaS Mass Endpoint Creation

This is a two-purpose article, one general and one specific. Generally, we'll configure powershell to manage your Azure subscription, and then specifically how to configure many endpoints at once.  

When I was working on my article Experiment: Application Server on Windows Azure I noted one peculiar issue. Setting up Windows Azure Endpoints is easy to do one at a time, but doing en masse is seemingly complicated. Fortunately, there is a relatively easy workaround using powershell Azure management.

Setup Powershell to Manipulate Azure

 

Download Azure Powershell

 

You can get the Powershell management plugins from this link. The main link uses the Web Platform Installer and several non-critical items are marked as pre-requsites. If you use WPI it will download and install those as well. Note that despite this assertion, the only thing that is really needed for PowerShell is the stuff that is (by default on a 64 bit OS) installed to "C:\Program Files(x86)\Microsoft SDKs\Windows Azure\PowerShell\Azure\*.*" after installing using the WPI. For that reason, I actually put this folder in my Skydrive; the whole thing is only 8.55MB, and you can load it directly without "Installing"(see below).

Setup Powershell Management

  1. Start Powershell as administrator
  2. Ensure you have your execution policy set to RemoteSigned (or unrestricted) with the command "Set-ExecutionPolicy RemoteSigned"
  3. Import the module with the command "Import-Module {Path to Install}\Azure.psd1"
  4. Get your account settings by typing "Get-AzurePublishSettingsFile". This will open up a web browser and download your settings file. You may need to log-in. Note: Ensure you keep this file in a secure location or dispose of it after import.
  5. Import that file by executing "Import-AzurePublishSettingsFile {path to downloaded .publishsettings file}"
You should now be able to manipulate your VMs and other services using powershell. To test this, try something like "Get-AzureVM"

Note: If you have multiple subscriptions in one account you'll need to use the command "Select-AzureSubscription {Subscription Friendly Name}>"

Now you should be good to go. Now let's set up some endpoints!

Mass Endpoint Creation

 

Let's say you want to create TCP port openings from 27000 to 27080 on one or many VMs. (This script will work for both scenarios) Creating them by hand would take quite some time. To accomplish this quickly with powershell, do the following:

If you haven't already, perform steps 1 and 3 above.

Here's the script with line by line discussion below. Note that this could be conflated to fewer lines but I've broken it out to be easier to understand. 



$VMs=Get-AzureVM -ServiceName "VMName"
foreach ($VM in $VMs)
{
    $p=27000
    do
    {
        Get-AzureVM $VM.name|Add-AzureEndpoint -LocalPort $p -PublicPort $p -Name TCP$p -Protocol TCP | Update-AzureVM
        $p+=1
    }
    until ($p -gt 27080)
}

note: PleaseKING below has a great example of how to get this to execute faster by not committing on a per port basis; check it out! 

Discussion:
$VM=Get-AzureVM -ServiceName "VMName" : Get the VM objects. To return all VMs and apply endpoints to all your VMs, just omit the "-ServiceName "VMName" portion.

foreach ($VM in $VMs) : Let's process these ports for each VM. Works with just 1.

$p=27000 : Start port. Change this to the first port you want to forward in.

Get-AzureVM $VM.name|Add-AzureEndpoint -LocalPort $p -PublicPort $p -Name TCP_$p -Protocol TCP | Update-AzureVM : Feed in the VM object | Add endpoint where -localport $p is the port, -Name TCP_$p is the defined port name, feel free to change and -Protocol TCP for TCP. Change to UDP if necessary | Commit changes

$p+=1 : Increment port by 1. Feel free to change the increment if you need to open different port groups

until($p -gt 27080) : The last port in the range to create.

That should do it! Note these will take awhile to setup; the per port provisioning is kinda slow.

Now that you've forwarded the endpoints, you'll need to open the ports on the VM firewall as well. To do this quickly, see Hey Scripting Guy!



Reference time:
If you have any questions or comments please let me know!

Saturday, March 16, 2013

Do You Need Virtual Machine Manager and VMM 2012 SP1 Installation

Do I need VMM?

 

That's a question I've heard many times and while there is alot of data out there I wanted to make a simple list to help those entertaining the same question. Here is the breakdown of what Microsoft offers with VMM above and beyond standard Hyper-V:

  • Centralized management and configuration support for Hyper-V, Xen Server, and VMWare.
  • It contains P2V Migration tools not included with standard Hyper-V.
  • One console for managing multiple hosts. While using standard Hyper-V you can have multiple hosts in one MMC, but you need to switch between them. 
  • Automatic "workload placement" i.e. automatically moving a guest from one host to another based on load. 
  • Tools for environment consolidation. (Identify idle guests, etc.)
  • Much more from a management perspective including tools facilitating hosting multiple clients. "Tenants". 
If any of these features are appealing to your business you should give VMM a try. Everything you need for a trial is available for free. (Win8 AEK, VMM, SQL Express) For licensing costs, see this blog post by the always sharp Scott Lowe and this FAQ published by Microsoft. Now that we covered that,let's install!

Installing VMM

 

Assumptions

  • We're talking 2012 SP1 here, so you'll need Windows Server 2012 
  • Internet Access to D/L the Win8 AEK (link below)
  • Domain and preferably Enterprise Administrator access (You'll see why) 
  • This has a SQL Database; I assume you know where you want to put that. "An intern with Excel" will not suffice.  

Prerequisites

  1.  First you'll need to download and install the Windows 8 Assessment and Deployment Kit on the server on which you intend to install 2012. When installing select "Deployment Tools" and "Windows Preinstallation Environment" only. 
  2. Service Account: This domain-based service account will need only Administrative access to the target server. Lesser access is not possible per Microsoft. For additional security lock the account down to being able to log onto that server only. While it is possible to run VMM with a non-domain account, I won't cover that because doing so loses functionality. If you haven't done a service account before make sure you create at least one dedicated OU and a good prefix or suffix for the account name. I use a prefix of S_.
  3. A container for the Active Directory based crypto keys. By putting these in AD you facilitate moving the server or having a highly available environment. Again, I will not cover the "local" option. There is conflicting information on how to implement this, but through testing I determined that you DO need to pre-create the DKM container. This article is correct on the steps to configure, but here is a short list: 
    1. Pick a location in AD for this container. Use ADSIEdit to create the container by navigating to where you would like it and right clicking target OU->New->Object->Container and name it. (I recommend VMMDKM to correspond with MFST doco) 
    2. (If you're not an "Enterprise Admin", "Domain" not enough) Right click the new CN, select properties, and switch to the "Security" tab, and add the username of the installer to have full control to "this object and all descendant objects". Click OK. 
    3. Make sure you take note of the distinguishedName; this can be copied easily by right clicking->properties->double click distinguishedName->copy to clipboard/paste to notepad or Edlin or vi or Lotus WordPro or WordStar.

 Let's Do This


  1. Insert the DVD (image) and start setup.exe. Hit "Install".
  2. Check "VMM Management server" and "VMM Console" if desired and hit "Next"
  3. Enter your Name, Company, and ProductID. You can do a "evaluation" edition if you don't have a key yet. Hit next, accept the service agreement, and hit next again. 
  4. Choose if you want to participate in the CEIP, and hit "Next". 
  5. Select your install directory and hit "Next". As a rule of thumb I recommend using a drive other than the system drive for  all apps and logs.
  6. Assuming you pass the pre-req check, note any warnings and hit "Next". 
  7. Select your SQL server. As noted above your installer account will need to have sufficient permissions to add a database. If you're setting up a lab and don't have a "real" SQL server available, check out SQL Express. Enter the appropriate info and click "Next".
  8. Now you'll need to enter the service account that we discussed above. Check the "Store my keys in Active Directory" and copy in the DN from earlier. Hit "Next". If you want to use the non-AD based option you can, but eventually your server will self destruct.
  9. On the Port Configuration screen, accept the defaults unless you know you'll conflict with another service on the box and hit "Next".
  10. Specify a location for the VMM Library share. Again, I recommend not putting this on the system drive. Don't worry about space at this time, you can always change this after the install. 
  11. Hit "Install" on the Installation Summary screen. 
  12. Make sure you update the server & VMM from Windows Update and party like it's 1999. 
Now that you've got it installed it's time to see what it can do. I'm not going to tackle that today, but here are a few other resources to get you started:

Have fun & if you have any questions, let me know!

Update 3/31/2013: Troubleshooting
  • Host Performance Counters read 0!  I was having an issue where VMM was missing all or some of the performance counters. Fortunately Kristian Nese published a fix that works well here

Monday, March 11, 2013

New 2012 Powershell CmdLets: Role Focus on NPS (Radius) Server

This will be one in a series of posts highlighting the new Cmdlets available in Windows server 2012 that didn't previously exist. I'll be breaking them down on a role-by-role (or feature) basis for easier reading. The first we'll be focusing on is the NPS server included with Windows Server, which is often used for RADIUS authentication.



Load the module: (on a 2012 Server\Win8 machine with the NPS server role or management tools loaded)

import-module NPS

Get the commands:

get-command -module NPS

CommandType     Name                                  
-----------     ----                                            
Cmdlet          Export-NpsConfiguration
Cmdlet          Get-NpsRadiusClient
Cmdlet          Get-NpsRemediationServer
Cmdlet          Get-NpsRemediationServerGroup
Cmdlet          Get-NpsSharedSecretTemplate
Cmdlet          Import-NpsConfiguration
Cmdlet          New-NpsRadiusClient
Cmdlet          New-NpsRemediationServer
Cmdlet          New-NpsRemediationServerGroup
Cmdlet          Remove-NpsRadiusClient
Cmdlet          Remove-NpsRemediationServer
Cmdlet          Remove-NpsRemediationServerGroup
Cmdlet          Set-NpsRadiusClient


Let's walk through these:

Export-NpsConfiguration: This is great; exports all configuration of the NPS server EXCEPT templates to an XML file for backup or import to a different server. Anything containing template information will be converted to information specific to that configuration item and exported, i.e. if a client profile uses a template shared secret the shared secret will export successfully but it will be an asset of that client configuration rather than having the config linked to the template. This will remain true even if the target server for importing the profile already has the template elements defined by the same name. Also note that if you have a SQL server configured for auditing that information will not be exported either. Security Warning: All information including shared secrets will be stored in clear text. Command example:


Export-NpsConfiguration c:\temp\NPSConfig.xml


Get-NpsRadiusClient,Get-NpsRemediationServer,Get-NpsRemediationServerGroup,Get-NpsSharedSecretTemplate: Enumerates the Radiusclient, RemediationServer(groups), and shared secret templates on the local server. Only the Get-RemediationServer cmdlet requires an argument. The others will show all items on the server and you can use common parameters to parse. Security warning: Get-NpsSharedSecretTemplate will display shared secrets in clear text.

Import-NpsConfiguration: When supplied with an XML configuration file generated by the Export-NpsConfiguration(above) it will import an NPS server configuration. As noted above you cannot import information regarding templates or SQL auditing, but everything else will come over fine. These two commands could be used in a scheduled task if desired to sync configuration from a "master" NPS server to others within the organization. Command example:


Import-NpsConfiguration c:\temp\NPSConfigFromThatOtherServer.xml


New-NpsRadiusClient, New-NpsRemediationServer, New-NpsRemediationServerGroup, Remove-NpsRadiusClient, Remove-NpsRemediationServer,Remove-NpsRemediationServerGroup: Commands to setup and remove NPS/Radius clients, remediation servers, and remediation server groups. Pretty straightforward; here's a New-NpsRadiusClient example:


New-NpsRadiusClient -Name "NameOfMyClientGroup" -Address "10.1.0.0/16" -AuthAttributeRequired 0 -NapCompatible 0 -SharedSecret "SuperSharedSecretxyz" -VendorName "RADIUS Standard"


Set-NpsRadiusClient: All this does is change a value of an existing client specification. This would be useful for doing batch updates of all client profiles. Take, for example, this command which would disable all client profiles:


foreach ($i in Get-NpsRadiusClient){Set-NpsRadiusClient $i.name -Enabled 0}


So here's a fun idea: Automate config changes all your NPS/Radius servers to have a master/slave relationship using a shared storage space, powershell, and task scheduler. It's as easy as 1, 2, 3! (Sheesh, did I just say that?)


  1. Create simple powershell scripts to export the configuration to a shared file space (on "master" NPS server) and import from the shared file space (on "slave" NPS servers)  You may want to version them...
  2. Create Scheduled task on the "master" to export however often you like and one scheduled task on each "slave" NPS to import that config. Make sure the import comes after the export
  3. Profit!
Quick notes: if doing this be aware that changes will flow automatically so if you ruin your master you'll ruin your slaves too. As noted above I'd recommend versioning the configuration files (use the date) so that you have a history of the changes, just make sure you're fully aware of the fact that the shared secret is in the clear. If you wanted to get really fancy to protect that you could use a common service account and EFS, but that's a little deep for this article. :) 

In the mood for some references? Me too!
Technet NPS Migration Guide
Technet NPS Server Migration (different)
Technet NPS Cmdlets (Note the referenced -full and -examples aren't actually in the files)
Technet: Export NPS Config

Any questions? Let me know. Have fun!


Wednesday, February 27, 2013

Azure IaaS (VM) Tip: Use Skydrive to Transfer Files Quickly

While working with Azure hosted VMs, I wanted an easy and secure solution to do one-off file transfers without opening too much up. I found that the web interface for Skydrive works perfectly! Here's a quick howto:

Assumptions:

  • You have an Azure VM you want to get files to. 
  • You have a skydrive account. 

Let's go:

  1. Throw your desired files into a folder in your skydrive. 



  2. Log into your Azure VM via RDP and and click "Configure this local server" in Server Manager



  3. Click "IE Enhanced Security Configuration" 
  4. Set it to "Off" Administrators. (Be careful after this; don't be browsing the web on this thing..) 



  5. Open IE, navigate to skydrive.live.com and login. 
  6. Navigate to the folder you want to copy to the VM; do not drill into it. Hover your mouse over it and check the box in the upper right. 



  7. Click "Download" to download a zip file of the folder structure to the VM! (cool that skydrive makes the zip on the fly) 
Enjoy!

Sunday, February 24, 2013

Experiment: Application Server on Windows Azure IaaS 90 Day Trial

Windows Azure now allows you to demo the IaaS (Infrastructure as a Service) model with a 90 day free trial. This is a welcome change and I thought I'd walk through the setup of something fun as an experiment: A mumble (murmur) server setup. Mumble is an open source voice chat platform that focuses on low latency and high voice quality. It's primary focus is for use when gaming, but my family uses it from time and time to "call" distant places because the low latency makes long distance chat less awkward. That said, this obviously applies to your app of choice, which is what makes this such a powerful option.

IaaS allows you to host full virtual machines in the Azure cloud. (Among other things) Pre-configured options currently include Windows (2012, 2008r2) and Linux. (CentOS, Ubuntu, Suse)

VM Management Dashboard


In this article, I'll walk you through signing up for Windows Azure, provisioning a basic 2012 server, and installing and configuring a serving platform.

Sign up


Navigate to http://www.windowsazure.com/en-us/pricing/free-trial/ and click "Try it now". You'll need to logon with your Microsoft (Live/Passport/etc.) and enter your credit card information to start an account. Note that after the 90 days you will need to cancel the account or you will be billed for anything you have setup.

Setup


After account setup you should be able to immediately log into the Azure management portal. After logging in (and browsing around; they've really done a nice job on this) click "New" in the bottom lefthand corner. To create the 2012 instance, select "Compute->Virtual Machine->Quick Create". You will then need to populate the following fields:
  • DNS Name: This is both the name of the machine and where it will be accessible on the internet. The cloudapp.net suffix will be added on the end of the name. Say, for example, you name it "megawidgetgenerator01". In that case you can find it on the internet by resolving "megawidgetgenerator01.cloudapp.net". Your name will need to be unique among other machines in that DNS zone. (see the green checkbox)
  • Image: What you want the VM to be. I'll be selecting "Windows Server 2012 Datacenter"
  • Size: This select how many cpus and how much memory you would like. After the trial (and perhaps during depending on usage) you will be charged relative to your resource utilization. "Larger" machines cost more per month. I'll be going with "Medium" for my test, which gives me 2 dedicated cores and 3.5GB of RAM. The processors used (as of the writing of this article) are the AMD Opteron 4171 HE, not a stellar performer but excellent in the cores-per-watt department which makes it a smart choice.
  • UserName: Fixed at this time to "Administrator" 
  • Password: for the admin account. Pick something good; this is accessible from anywhere. 
  • Location: Which datacenter do you want it in? Pick the geo closest to your users. 


After filling that out, click "Create Virtual Machine".  Your new VM will be provisioned within a few minutes. You can now connect to your new server by navigating in the Azure management portal to Virtual Machines->Select your new VM-> Connect (on the bottom). This will send you a .rdp file to connect via RDP, but know you can just connect to the hostname you selected at any time; RDP is automatically enabled and unblocked by the default image.


Configuration


After connecting, you probably want to run Windows Update to ensure everything is patched up. After that, do the following:

  • Install your application. (Mumble in my case) 
  • Unblock the ports in Windows Firewall
  • Set the ports up as Endpoints in Azure EDIT: See my article here.

Windows Azure defeats the IPv4 exhaustion issue by NATing VMs. (boy IPv6 will be nice) Because of this, you need to setup enpoints in Azure so they can update their NAT rules to forward ports on the public IP (visible when you click your VM and look under "quick glance") to the private IP associated with your machine. The current limit for endpoints is 150 ports.  This should be more than enough for most applications. To accomplish this: refer to the following:

Overall I'm impressed. I'm very excited to work with Azure in the future. With these capabilities, I feel I've always got another datacenter on tap for any of my clients I can use for load balancing, DR, or as a primary site for whatever they may need.

Friday, February 15, 2013

Server 2012 Hyper-V + RDP + RemoteFX = a Delicious "Sangwich" of Cheap VDI

Oh man. Microsoft has done well on this; VDI/RDP/HyperV/RemoteFX have come together very nicely in 2012. The incremental improvements over the last 4 or so years to RDP, Hyper-V, and RemoteFX have made a great platform for cost effective VDI. This article will outline setting this entire environment up on one Server 2012 Datacenter box, but this could be scaled to as many machines as you need. (Add VMM for management in a large deployment) In this article I'll be walking through a basic setup of a Hyper-V Virtualization Host, Connection Broker, Web Access, a pool, the whole 9.

Assumptions:
  • You have at least one 2012 Hyper-V host setup.
  • You've got at least one 2012 server ready to go as the other roles. This can be a VM. 
  • You've got a sangwich. You'll need one, this is a bit of a lengthy install. 
Starting in seemingly reverse order will make this while thing easier; you'll see why.

Create an Template/Image to use For VDI

BTW, more template info here.
  1. Create a Virtual Desktop template by making a new VM with (generally) default settings. Insert the ISO and install the OS and make sure your product key is applicable to be in a your target VDI environment  (i.e. MAK with a SA or KMS as applicable) 
  2. After installing the OS, execute sysprep or something similar. On windows 8, that will be located under %SystemRoot%\system32\sysprep\sysprep.exe. Make sure you generalize and restore to OOB Experience; select shutdown when complete. 

Install Remote Desktop Services Components

  1. Prior to starting the RDS installation, you need to add all servers involved in your deployment to server manager to enable them as options during deployment. To do so, click "Add Servers To Manage" from the start screen of server manager and add any servers that will be part of the setup. (Hyper-V host, RDS Connection Broker, Session Host, etc.) 
  2. After adding the server(s) in question, start the RDS deployment by clicking "Manage->Add Roles and Features" from within server manager. 
  3. Proceed to the "Installation Type" and select "Remote Desktop Services installation" and click "Next".  
  4. On "Deployment Type" select "Standard deployment" and click "Next". Unless you've been through this before, I don't recommend Quick Start as it skips some things you should know. 
  5. On "Deployment Scenario" we'll be going through "Virtual machine-based desktop deployment". Select it and click "Next". Note that both options here have their uses, we're just covering VDI because it's a newer option. For more information on the differences, see this blog post by Yung Chou. 
  6. Based on our choices, it should notify you that RD Connection Broker, RD Web Access, and RD Virtualization Host will be installed. Review and click "Next". 
  7. You will be prompted to select a machine from your pool to host the RD Connection Broker role. Select the host(s) you would like for this role, move them to the right plane, and then click "Next". The Connection Broker distributes load across multiple hosts (if applicable) and maintains session information to ensure users are directed to the proper session or virtual desktop. For more information, see this TechNet article. This role can be hosted by a virtual machine. 
  8. Now you'll be prompted to select the RD Web Access server. In smaller deployments it is very common to place this on the same server as the RD Connection Broker. In larger environments you'll need to take external connection needs and security into account. Either click "Install the RD Web Access role service on the RD Connection Broker server" or select the server(s) you do want and click "Next". This role can also be hosted by a virtual machine. 
  9. Time to select virtualization host(s). This role cannot be hosted by a virtual machine for obvious reasons. Select the machne(s), move them over, and click "Next". 
  10. You'll be presented with the confirmation screen; review the information and click "Deploy" to create the whole setup. 
  11. The progress of each role installation will be displayed; do not be suprised if this takes some time. 

Setup a VDI Collection

  1. In server manager, click "Remote Desktop Services" and then click "3> Create Virtual Desktop Collections
  2. Click "Next" to bypass the before you begin section and then give your collection an appropriate name and click "Next" again. 
  3. Select the type of collection you want, Pooled virtual desktops or Personal virtual desktops. There is a lot that goes into this decision, but as a rule of thumb you can think of it like this: Pooled virtual desktops = many (users) to one relationship and Personal virtual desktops=one to one relationship. For my lab I'll be doing Personal virtual desktops, so please note that the options listed after this may be slightly different should you want Pooled. Unless you know you want otherwise leave "Automatically create and manage virtual desktops" checked and click "Next".
  4. When prompted with "Virtual Desktop Template" select the template we created in the first step and click "Next". 
  5. (This step unnecessary for pooled desktops) In most cases, you'll want to leave "Enable automatic user assignment" selected because that will give the requesting user access to a newly provisioned VD. If you desire, select "Add the user account to the local administrators group on the virtual desktop" and click "Next". 
  6. For "Virtual Desktop Settings" you should provide your Sysprep answer file; this will contain all the provisioning settings for your company. Since this is a lab setup in my case, I'll be selecting "Provide unattended installation settings". Click "Next".
  7. You need to know where you want to place automatically created VDI objects in Active Directory. After making that determination you'll need to paste in the path to the OU. Then, we'll need to generate a powershell script and execute it on a machine that has the Active Directory management tools installed on it. First things first, navigate to a machine with the Active Directory management tools installed and logon as an account with appropriate domain privs. On that machine:
  8. Open Active Directory Administrative Center and navigate to where you would like the VDI machines go to; create the OU if necessary and double click to go into it. Select the navigation plane (next to the arrow keys on the top) and it will give the DN. Copy and paste this DN to specify in setup. 
  9. Switch back to the RDS server. Set the time zone and then select "Specify the distinguished name of the organizational unit" and paste in our DN from the other server; DO NOT click Next yet. 
  10. After pasting the DN in, click the "Generate script" at the bottom of the window and copy all the contents of the script.
  11. Switch back to the AD server and open notepad. Copy the script into notepad and save it to a temporary location, i.e. C:\temp\Grant-RDSRights.ps1.
  12. (Still on AD server) Open Powershell as an administrator. If needed, execute "Set-ExecutionPolicy unrestricted" to allow script execution. 
  13. (Still on AD server) Execute the script you just saved. If your rights are correct you will get a success message. 
  14. Switch back to the RDS server and click "Next". If it doesn't work you may need to wait for the permissions to replicate. BUG WARNING: Ensure you do not have any "." characters in your DN. (I.E. in you OU names) If you do, this will not work. You will get the message "The RD Connection Broker server does not have access to add the virtual desktops to the Active Directory domain. Configure access by using the Active Directory page of Deployment Properties." despite the fact that permissions are in fact correct. (I wish I could bill someone for time wasted figuring that out) 
  15. Select the Active Directory Group, # of initial virtual desktops, the machine prefix, and the machine suffix. I recommend making one AD group per collection to accurately track who has access to what. As for a machine prefix/suffix, pick something that will work for your organization. I use VDI- for a prefix. Click "Next". 
  16. The "Virtual Desktop Allocation" screen will come up and allow you to distribute your VDI machines across multiple hosts if desired. Distribute accordingly and click "Next". 
  17. For "Virtual Desktop Storage" select what type of storage you would like to utilize for these VDI machines. You have all your standard options here, including Cluster Shared Volumes. For more on CSVs, check this out. Select your desired disk location and hit "Next". 
  18. The confirmation screen will come up; use this to review your settings and click "Create". 
  19. This may take awhile depending on your disk configuration and it may even report to the window that it's not responding. Don't worry, it'll complete eventually. 
That does it! You've now got your stable of virtual machines ready to dole out to deserving employees. If you're particularly astute you will be able to convince management that there is a monthly cost for each desktop payable to your bank account.

Managing Your Collection

Adding a Desktop

  1. Open Server Manager either on the RDS server or a machine with that server registered in its server manager. 
  2. Click "Remote Desktop Services"
  3. Under "Collections", click your collection name. 
  4. Under "Virtual Desktops" on the right, click "Tasks->Add Virtual Desktop"
  5. Specify how many virtual desktops you would like to add. 
  6. Specify on which server you would like to add them.
  7. Click "Create"
  8. You will be notified when the creation request is complete. 

Assigning a Desktop

  1. Open Server Manager either on the RDS server or a machine with that server registered in its server manager. 
  2. Click "Remote Desktop Services"
  3. Under "Collections", click your collection name. 
  4. Right click on the VDI machine you would to assign and select "Assign Virtual Desktop". 
  5. Specify a user to assign to and click "Assign". Note this user must be in the group you specified as the user group for this collection above. 

Configuring Licensing


This is a topic for a whole other article, but for now have a look a this Technet article and this one as well. 

Accessing Your Collection

There is enough here for another article, but to get you started: 

  1. Using IE (preferably) navigate to https://your.rdweb.server/RDWeb 
  2. You'll probably get a cert warning; you can fix that later by installing the proper web cert on your IIS server. 
  3. Log in with your assigned user and double click on the collection you created. 
  4. Enjoy your fresh install of Dos 5.0. (I'm assuming that's what you are using) 
Next up, RemoteFX. Update: RemoteFX Article here.

Monday, February 4, 2013

Installing nVidia Consumer Drivers on Server 2012 Core for RemoteFX


I'm wanting to establish Microsoft RemoteFX in my lab, and to do so, one needs a dedicated 3d accelerator. Obviously, nVidia didn't make the drivers with Server 2012 (now 2016 as well, see below) Core in mind. To accomplish this, we need do the following:

1> Download the newest drivers from nVidia. (Note the later half of these points will probably work on ATI cards as well, you just need to unpack the drivers)
2> Execute the driver setup directly on core server the and select a temporary directory. 
3> Hit "OK"; the installer will crash because it's uncomfortable in the lovely world of server core.
4> Navigate to the display.driver directory underneath the extracted files in the temporary directory you selected earlier. You should find the .inf files in this directory. For nVidia it is nv_disp.if. Update 5/3/2015: the .inf file is now nv_dispi.inf, thanks bearkiter.
5> From cmd.exe, execute "pnputil -i -a nv_disp.inf"
6> The screen will blank! Don't be afraid. After completion, you should see a screen that looks like the shot below. (yes the borders are gone)
7> Assuming it's OK to do so execute "Shutdown /r /t 0" to reboot the machine.

I'm working on another article to cover VDI/RemoteFX. Stay tuned. Update: Article here.



Update 2/3/2017: Confirmed working on Windows 2016! Consumer grade hardware works in the lab as well.

Monday, January 28, 2013

Add a GUI to Server Core 2012 and Overcoming Error: 0x800f0906

When Microsoft released server 2012 they included a very welcome new feature that allows you to install and remove the GUI on Windows Server core. There are a couple different levels, essentially one with the desktop experience and one without. While it seems this should be a straightforward process, it turned out more complicated than one would expect; here's how to do the install and work around those issues:

Note: You may see both Install-WindowsFeature and Uninstall-WindowsFeature referenced elsewhere; as Add-WindowsFeature and Remove-WindowsFeature. There is no difference; the later two are aliases for the first two.

Adding the GUI



At the most basic level, you need the following command to add the GUI on server core Install-WindowsFeature Server-Gui-Shell, Server-Gui-Mgmt-Infra . Unfortunately, this doesn't take into account the fact that the binaries we want aren't included on server core. (we'll get into this a bit more under removal) To re-mediate this, insert the Server2012 installation media or an equivalent source and modify the command with the -source parameter accordingly.


powershell

Install-WindowsFeature -source:D:\sources\sxs\ Server-Gui-Shell, Server-Gui-Mgmt-Infra
after completion:

shutdown /r /t 0

This will work if you are NOT using a WSUS server, which I suspect alot of you are. More on that below. This install may take awhile, so be patient.

Removing the GUI


Powershell

Uninstall-WindowsFeature -remove Server-Gui-Shell, Server-Gui-Mgmt-Infra
after completion:

shutdown /r /t 0

By using the -remove switch you will delete the binaries rather than just deactivate them.


Troubleshooting/Dealing with WSUS

So this procedure is not without its flaws. Unfortunately if your server is pointed to a WSUS server you'll have problems. Note that this is a different issue than the one experienced with using Server 2012 against a WSUS 3.0 server; in this case we're using a new WSUS 2012 server. The error you'll see will be 0x800f0906, which has to do with getting updates for the binaries. It seems there is an issue retrieving those binaries when pointed to said WSUS server. The entries in the %SystemRoot%\windowsupdate.log file look like this:

Not Connected to WSUS/ Successful Update:


2013-01-23    12:17:45:088     748    7bc    Agent    *************
2013-01-23    12:17:45:088     748    7bc    Agent    ** START **  Agent: Finding updates [CallerId = TrustedInstaller FOD]
2013-01-23    12:17:45:088     748    7bc    Agent    *********
2013-01-23    12:17:45:088     748    7bc    Agent      * Include potentially superseded updates
2013-01-23    12:17:45:088     748    7bc    Agent      * Online = Yes; Ignore download priority = No
2013-01-23    12:17:45:088     748    7bc    Agent      * Criteria = "CategoryIDs contains '75f164f7-89ef-4f1c-add4-c5404c8c117f' and UpdateID='20b172e5-d0aa-4721-8186-debafe5dc89f'"
2013-01-23    12:17:45:088     748    7bc    Agent      * ServiceID = {00000000-0000-0000-0000-000000000000} Third party service
2013-01-23    12:17:45:088     748    7bc    Agent      * Search Scope = {Machine}
2013-01-23    12:17:45:088     748    7bc    Agent      * Caller SID for Applicability: S-1-5-18
2013-01-23    12:17:45:541     748    7bc    Misc    Validating signature for C:\Windows\SoftwareDistribution\WuRedir\9482F4B4-E343-43B6-B170-9A65BC822C77\wuredir.cab:
2013-01-23    12:17:46:088     748    7bc    Misc     Microsoft signed: Yes
2013-01-23    12:17:46:088     748    7bc    Misc     Infrastructure signed: Yes
2013-01-23    12:17:46:103     748    7bc    EP    Got 9482F4B4-E343-43B6-B170-9A65BC822C77 redir Client/Server URL: "https://fe1.update.microsoft.com/v6/ClientWebService/client.asmx"
2013-01-23    12:17:46:463     748    7bc    PT    +++++++++++  PT: Starting category scan  +++++++++++
2013-01-23    12:17:46:463     748    7bc    PT      + ServiceId = {9482F4B4-E343-43B6-B170-9A65BC822C77}, Server URL = https://fe1.update.microsoft.com/v6/ClientWebService/client.asmx
2013-01-23    12:17:47:954     748    7bc    PT    +++++++++++  PT: Synchronizing server updates  +++++++++++
2013-01-23    12:17:47:954     748    7bc    PT      + ServiceId = {9482F4B4-E343-43B6-B170-9A65BC822C77}, Server URL = https://fe1.update.microsoft.com/v6/ClientWebService/client.asmx
2013-01-23    12:17:49:032     748    7bc    Agent      * Added update {20B172E5-D0AA-4721-8186-DEBAFE5DC89F}.200 to search result
2013-01-23    12:17:49:032     748    7bc    Agent      * Found 1 updates and 4 categories in search; evaluated appl. rules of 163 out of 309 deployed entities
2013-01-23    12:17:49:063     748    7bc    Agent    *********
2013-01-23    12:17:49:063     748    7bc    Agent    **  END  **  Agent: Finding updates [CallerId = TrustedInstaller FOD]
2013-01-23    12:17:49:063     748    7bc    Agent    *************

Connected to WSUS/ Failed Update:


2013-01-25    00:02:42:866     756    6d8    Agent    *************
2013-01-25    00:02:42:866     756    6d8    Agent    ** START **  Agent: Finding updates [CallerId = TrustedInstaller FOD]
2013-01-25    00:02:42:866     756    6d8    Agent    *********
2013-01-25    00:02:42:866     756    6d8    Agent      * Include potentially superseded updates
2013-01-25    00:02:42:866     756    6d8    Agent      * Online = Yes; Ignore download priority = No
2013-01-25    00:02:42:866     756    6d8    Agent      * Criteria = "CategoryIDs contains '75f164f7-89ef-4f1c-add4-c5404c8c117f' and UpdateID='337d9460-e236-40a9-91f3-a6831e113867'"
2013-01-25    00:02:42:866     756    6d8    Agent      * ServiceID = {00000000-0000-0000-0000-000000000000} Third party service
2013-01-25    00:02:42:866     756    6d8    Agent      * Search Scope = {Machine}
2013-01-25    00:02:42:866     756    6d8    Agent      * Caller SID for Applicability: S-1-5-18
2013-01-25    00:02:42:866     756    6d8    EP    Got WSUS Client/Server URL: "https://wsus.internal.lan:8531/ClientWebService/client.asmx"
2013-01-25    00:02:42:882     756    6d8    PT    +++++++++++  PT: Starting category scan  +++++++++++
2013-01-25    00:02:42:882     756    6d8    PT      + ServiceId = {3DA21691-E39D-4DA6-8A4B-B43877BCB1B7}, Server URL = https://wsus.internal.lan:8531/ClientWebService/client.asmx
2013-01-25    00:02:42:913     756    74c    AU    Triggering Offline detection (non-interactive)
2013-01-25    00:02:42:913     756    6d8    Agent      * Found 0 updates and 0 categories in search; evaluated appl. rules of 0 out of 0 deployed entities
2013-01-25    00:02:42:913     756    6d8    Agent    *********
2013-01-25    00:02:42:913     756    6d8    Agent    **  END  **  Agent: Finding updates [CallerId = TrustedInstaller FOD]
2013-01-25    00:02:42:913     756    6d8    Agent    *************

Note that no updates were found.

Work Around: 

We're going to use group policy to work around this issue. Assuming you have access to do so or can convince those responsible to do so, perform the following: (note that the GPO containing the setting below cannot be overridden by a higher level GPO or this will not work)

You have two options, enable an alternative install location as outlined in this article from Microsoft, or temporarily override the WSUS setting by doing the following:

  1. Without binding it anywhere, create a new group policy object called Computer_Settings_WSUS_Disable or something similar that adheres to your naming standards.
  2. Navigate to the "Scope" tab on that group policy object and remove the "Authenticated Users" principal under "Security Filtering"
  3. Click "Add..." and add the computer object in question. You'll have to change the object types to include computers. 
  4. Right click the GPO object and select "GPO Status->User Configuration Settings Disabled". 
  5. Edit the GPO and set the setting "Computer Configuration->Policies->Administrative Templates->Windows Components->Windows Update" and change "Specify intranet Microsoft update service location" to "Disabled". This will revert it to Microsoft.
  6. Right click on the OU you would like to bind it to and click "Link an existing GPO..." and select your newly created GPO.
  7. Do a gpupdate /force on your target server and execute the command again. No reboot should be necessary. 


After completing the update feel free to un-link or delete the GPO object.


Hopefully that gets you GUI-ing. Here are some additional links below for more reading if you desire. Feel free to leave questions in the comments!

Microsoft Ask the Directory Services Team: "Windows Server 2012 Shell game"

How-To Geek: Turn the GUI off and On in Windows Server 2012

Yung Chou: Windows Server 2012 Installation Options

Jason Yoder: Error when moving from Core to full GUI in Server 2012



Friday, January 18, 2013

HOWTO Connect Powershell to SQL Server

In this article I'll be walking you through using Powershell to connect to SQL database. The objective is to be as straightforward as possible while providing context the whole way. Remember that lines marked with # are comments. Some of these will get long because we're trying to provide in-line context.

Assumptions:

  • Powershell 2.0 or higher
  • Connecting to a MS SQL server; for other connection strings see the excellent connectionstrings.com
  • Appropriate access to the SQL DB in question with your currently logged on account
  • Guts. 

Forward (or, WTH are we doing?!)

We'll be using two different objects for this operation: System.Data.SQLClient.SQLConnection and System.Data.SQLClient.SQLCommand. The first is a connection object that allows you to attach to the DB, and the second is a command object that allows you to specify and submit your command. Both these objects are part of the .NET framework, so they should be present on any machine that can run Powershell. Avoid using Microsoft.SqlServer.Management.Smo.Server unless you need to (and you'll know it) because it requires the SQL tools to be installed. 

In this first example, we'll be doing a query and returning the results. I won't be covering specifying UserID and PW in this because that relies on 1> SQL authentication and 2> Stores UserID and PW in the script. Bad idea. 

Setting the Stage

Let's first declare some of our variables to keep things clean down the line.

 #Declare our SQL server name; Make sure to use Server\Instance for instances, or Server:Port if you're on an instance and don't have the access to the SQL Browser service (UDP 1434). Also, try to use the FQDN because it's good practice and will insure NETBIOS issues won't trip you up.  
 $SQLServer="my.server.here"  
 #Provide the database name, i.e. "Northwind"  
 $SQLDBName="DATABASE"  
Now let's get to the meat; create objects, define properties, and open the connection. Here are reference links for the concepts in this section, followed by the comments and code:

System.Data.SQLClient.SQLConnection
System.Data.SQLClient.SQLCommand
ConnectionString Property
 #Create the SQL Connection Object  
 $SQLConn=New-Object System.Data.SQLClient.SQLConnection  
 #Create the SQL Command Ojbect (otherwise all we can do is admire our connection)  
 $SQLCmd=New-Object System.Data.SQLClient.SQLCommand  
 #Set our connection string property on the SQL Connection Object and tell it to use integrated auth, hopefully kerberos  
 $SQLConn.ConnectionString="Server=$SQLServer;Database=$SQLDBName;Integrated Security=SSPI"  
 #Open the connection  
 $SQLConn.Open()  
Now we'll define the query and execute. 

Devguru t-sql reference
 #Define our Command with a parameter (we will cover this below)  
 $SQLCmd.CommandText="SELECT [FOO],[BAR] FROM [dbo].[table] WHERE [COLUMN] = @smalls"  
 #Provide the open connection to the Command Object as a property  
 $SQLCmd.Connection=$SQLConn  
 #Set the WHERE clause in a variable to be referenced in the parameter (See section below)
 $WhereClause="smalls"
 #Prepare parameters  
 $SQLCmd.Parameters.Clear()
 $SQLcmd.Parameters.Add("@smalls",$WhereClause)  
 #Execute this thing  
 $SQLReturn=$SQLcmd.ExecuteReader()  
 #Init arrays to handle multiple returns
 $TheFooReturn=@()
 $TheBarReturn=@()
 #Parse it out  
 while ($SQLReturn.Read())  
 {  
      $TheFooReturn+=$SQLReturn["FOO"]  
      $TheBarReturn+=$SQLReturn["BAR"]  
 }  
 #Clean it up  
 $SQLReturn.Close()  
 $SQLConn.Close()  

Bonus Section: Avoiding SQL Injection

Note the lines $SQLCmd.CommandText="SELECT [FOO],[BAR] FROM [dbo].[table] WHERE [COLUMN] = @smalls", $WhereClause="smalls" & $SQLcmd.Parameters.Add("@smalls",$WhereClause). By using @ to set that value to a parameter we can later associate the parameter to the variable which will sanitize the input if it is provided by an external data source. (Prompt, file, etc.) This will protect from SQL injections; if we had used standard variable in the first place you could inject an inline SQL statement. By adding it as a parameter SQL will essentially treat it as a string. Thanks to my buddy Austin Peters for the education on this. :)

Closing Thoughts:


  • You can have multiple SQL connections open at once. When you do so, name your object variables in a way that you can keep track of the DB that variable represents
  • To do something other than a query (INSERT, etc.) set the SQLCmd.CommandText appropriately and change the statement SQLcmd.ExecuteReader to SQLcmd.ExecuteNonQuery. 
For more information, see this post by Don Jones. 

Thursday, January 10, 2013

Quick Hyper-V VM Templates

Here's a quick guide on how to clone Server 2012 machines in Hyper-V:

Assumptions:  

  • You've decided on a standard for you VM folder structure. I won't go into detail in the steps, but if you haven't I'll make a recommendation here. This is how I do it: 
    • {Drive}:\VM\VMName\Virtual Hard Disks
    • {Drive}:\VM\VMName\Virtual Machines
  • You know the basics of VM creation, etc. Perhaps I'll cover that stuff in another article. :)
  • You're making a template server 2012, which comes with sysprep. If you're doing another MSFT OS, you should DL and leave sysprep on the image before you shut it down. If it's Linux don't worry about it.

Make the Template

Note: Do not take any snapshots of the template machine because our simple copy method won't work with snaps. If you must have them, you'll need to use the Hyper-V export functionality.
  1. Setup a new Hyper-V VM from scratch. The defaults on hardware allocation should be fine unless you're templating an older OS that uses a SMP or Uni processor kernel; in that case give it one or multiple CPUs as you desire. Set the boot disk size to your standard size now and keep it thin provisioned. (you can expand after building if needed) I recommend 60GB or more for newer versions of Windows server. After a couple years that SXS folder will get pretty big.  
  2. When naming the machine, pick something meaningful like "_Template_Server_Datacenter_2012_NoGUI" or "ZZZ_Template_CentOS_6_3" or "_Template_OS/2_3_0_Warp_with_emulated_MCA"
  3. After doing basic setup, patch the machine up as much as possible.
  4. If you want to install/configure anything else on this template so that it will be present on any machine, do so now.
  5. (Windows Only)Navigate to the sysprep folder. (c:\windows\system32\sysprep on 2012) and execute sysprep.exe
  6. (Windows Only)On the sysprep screen, select "Enter System Out-of-Box Experience (OOBE)" (that's a mouthful) and check "Generalize" then change the "Shutdown Options" to "Shutdown" and click "OK". Sysprep will do the work and then shut down the server.


  7. Document the admin password & shut it down. 

How to Use the Template

  1. Make a new folder for your VM per your standards.(named appropriately, etc.)
  2. Copy the vhdx (or vhd) to your new folder. 
  3. In the HyperV manager create a new VM (named the same as you did in step 1) and spec the hardware appropriately but stop when you get to the disk. 


  4. Specify the disk you just copied over from the template and finish the wizard.
  5. Fire up the new VM
  6. (Windows Only) Complete the "OOBE" including entering a product key and a new admin password.
You did it! Depending on how often you use the template it will eventually make sense to fire up the template as a vm, customize it, patch it, and re-sysprep it. Note that according to this, the SID is generated upon reboot, so this template should provide a unique SID every time. 

Tuesday, January 8, 2013

Just take my monies! How to fix "Something happened and your purchase can't be completed" In Windows 8

I'm trying to buy an app in the Windows store on Windows 8 and I'm greeted with this message:

Amazing. It's like a riddle. Here's how to fix it:
  1. In the Metro(oops!) interface, open up the charms bar and select "Settings->Change PC Settings"
  2. Select "Users"; your account should be referenced on the right pane. 
  3. (Variable) Most folks will need to click "Switch to a local account", but if you, like me, are on a domain account that is linked to your MSFT ID, you will need to click "Disconnect from your Microsoft account". 
  4. Log out, then back on. 
  5. Buy something from the Windows Store. You should be prompted for your ID and it *should* (see below if not) work. 
  6. You can now re-link your account by navigating to "Settings->Change PC Settings->Users" and linking your account under your username on the top right plane.  You'll be prompted for your e-mail, password, and which settings you would like to sync during the process.
However

If this didn't work for you like it didn't for me (why'd I write it then!?!) you may need to look deeper. In my case it turned out being the fault of a toxic combination of Displaylink software and Nvidia drivers. While the Displaylink folks noted fixes in their latest driver release I wonder if it didn't also have something to do with the fact that the NV drivers aren't all signed properly. To help determine your problem, try the following: 
  1. Re-create the issue by trying to purchase your app again. 
  2. Bring up the charms bar and hit the "Start" charm to bring up the Met..Modern UI interface.
  3. Start typing "reliability" and click "Settings" then select "View reliability history". 
  4. Look for a report from the time frame in which you re-created the problem. In my case, I had issues from "Credential Manager UI Host" and "CredentialUIBroker.exe"
  5. "Right click crash report->View Technical Details". 
  6. Look for "Faulting module path". In my case it was nvwgf2umx.dll, provided by nVidia. Taking a look at that DLL, I noted it wasn't signed correctly. 


This (and procmon, but that's an article for a different day) is what led me down the track of investigating the graphics drivers. Odd when graphics drivers can be the cause of your inability to buy something from the Windows store. Hopefully in the future MSFT builds a DRM/ID testing path tool that can be used to improve this troubleshooting routine. 

Postscript: While the fix in my case was more on the Displaylink software side, I found it interesting that the newest nVidia drivers still aren't signed right. The signing cert traces back up through the "Microsoft Digital Media Authority 2005" CA which hasn't been valid for quite some time. Two driver revs ago, however, the signing was done correctly. Someone's dev box @ NV needs attention. :) Update 4/21/2014: NVidia contacted me regarding this issue we determined that the "Microsoft Digital Media Authority 2005" certificate is actually "baked into" Vista and higher operating systems. This seems a relatively well hidden fact, but it was revealed in this paper by Symantec. Interesting to say the least... anyhow their cert still has a potential revocation issue and they are working to resolve it.

If this still doesn't work, take a look @ the Windows store logs @ %USERPROFILE%\AppData\Local\Temp\winstore.log and %windir%\temp\winstore.log . Good luck!