Tuesday, September 27, 2011

User Impersonation in .NET

Recently, I've been working on a tool to manage deployments to a web farm. As part of this task, I had to modify our current tool to impersonate a shared login to perform the actions on the various servers. This was so the IT group would not have to grant access to a large number of users. This can be done in .NET, but the approach you have to take to impersonate another user is different depending on the action you are taking. While updating the program, I encountered three scenarios which had to be addressed in different ways.

Scenario #1: Executing .NET code in the current Thread
Scenario #2: Spawning a new Process in .NET
Scenario #3: Making a WMI request

Scenario #1: Executing .NET code in the current Thread
Executing .NET code as a different user may be necessary when performing disk operations, network operations, manipulating services, or other tasks that require security permissions. To start the Impersonation, the WindowsIdentity.Impersonate() method needs to be called with an authorization token for the impersonated user. This entire process requires making an external call to the Windows API to authenticate the user. While it sounds difficult, the MSDN page for the Impersonate() method provides a working sample that can be used as a basis for your own code.

Scenario #2: Spawning a new Process in .NET
Creating a new process already requires setting up a Process object or a ProcessStartInfo object. To set this object to execute as a different user requires just a bit of extra work to pass in a username and password. The following code snippet shows how to create a ProcessStartInfo object to start the command prompt as an Impersonated user.



String userName;
SecureString password;

// Code to get and set userName and password.

ProcessStartInfo startInfo = new ProcessStartInfo(“cmd.exe”);
startInfo.UserName = userName;
startInfo.Password = password;
// Add other parameters to startInfo as needed
Process.Start(startInfo);


Scenario #3: Making a WMI request
A WMI request queries the current or a remote server for system information to monitor the system. This functionality resides in the System.Management namespace, and isn't a common one to work with. WMI does allow for the queries to be ran as another user by creating a ConnectionOptions object, as the below example outlines.



String userName;
SecureString password;

// Code to get and set userName and password.

ConnectionOptions connectOptions = new ConnectionOptions();
options.UserName = userName;
options.Password = password;

ManagementPath path = new ManagementPath(“path to wmi object to query”);
ManagementScope scope = new ManagementScope(path, connectOptions);

// Once we have a scope object, we can either create an ObjectQuery object and query that way
scope.Connect();

ObjectQuery query = new ObjectQuery(“query to execute”);
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection collection = searcher.Get();

// Or we can create an ObjectGetOptions and a ManagementObject
ObjectGetOptions options = new ObjectGetOptions();
ManagementObject mgmtObject = new ManagementObject(scope, path, options);
mgmtObject.Get();
// Can now retrieve values from ManagementObject like a Dictionary
string value = mgmtObject[“key name”].ToString();

Saturday, September 24, 2011

Be careful what you say to customers

I've seen a few articles this week regarding Netflix and how they should have handled the price hike and the splitting of the company into 2 separate entities. Cringely tookto his pulpit to defend the move stating that with the name 'Netflix', it should be obvious that movie streaming was the plan the entire time. Elsewhere on Hacker News, an article popped up that provided an example of how Netflix should have handled the news this week. One of my favorite responses came from the Oatmeal explaining why thecompany split into two.

But, not being a Netflix user, this news doesn't affect me a whole lot nor can I add anything to the conversation that others have not already said. However, on Friday my wife received a newsletter email from our local book store. Our local bookstore is your typical local bookstore, small, slow moving stock, but it has a warm, rich atmosphere and a cat who lives at the store. But, the staff seem ignorant to the World Wide Web, as my wife once inquired about a book series and it took an excruciatingly long time for them to look it up on their computer. Their web presence is non-existent outside of a Facebook page. And while the store has a lot of good books, it can take them quite a while to turnover their stock.

The email itself started out generic enough, explaining some of the upcoming events and address some comments from customers regarding the loss of the local Borders. While their sad that a larger showroom of books is leaving, their hope that it will mean more business for them.

If the letter had stopped there, I would have deemed it a normal business letter and moved on. However, the letter quickly became awkward as it outlined the challenges the local bookstore is having. I'm not really sure these need to be listed in a newsletter, but rather kept in an internal document in the back office. I'm sure if you think about it for a moment, you can list the challenges bookstores face yourself.

Go ahead.



I'll wait.



Done? Good.

So here's what they listed: Internet, competition with eBooks (as many small stores can't publish eBooks), books being sold in lots of places, such as Walmart and such, and the Local Library.

Firstly, the whole list is much like going to a dinner party where the host and hostess reveal the difficulty they had in throwing the party. I, as the guest (or shopper in this case), don't really care about the difficulty in running the store. Second, many parts of the list come off as whiny, such as when the list claims the library is a competitor for local events and they seem to have an unlimited source of funds to attract events. Or when the list complains about the Internet and how people will shop in the store only to later buy the books from the internet, either from home or online.

Further on in the email, it hints that the business had to make several sacrifices and if business does not improve, further changes will have to be made. The letter then finishes with a Refer a Friend program for the email subscribers in hopes to bring in more clientele. Most of the letter reads as a self-indulgent, whiny prose later, and my desire to stop by the book store vanished. Up until I read the letter, I was planning on stopping by this weekend, yet now, I'll be shopping the Internet.

What the letter should have done is start off by describing the Refer a Friend program while briefly mentioning their hope that while it is sad to see a showroom of books leaving, they hope to see more foot traffic. Then, the letter could transition to discuss some upcoming events, then shift to another announcement, that the store will begin selling books online in an effort to compete more and to provide another avenue to sell their books and rotate stock. While this may mean a bit of a change to the business, it would be good for the shoppers, as new books should arrive more often and with more variety.

In a market where it's common knowledge that all the competitors are hurting and struggling, you can't whine to your customers; you have to take action.

Tuesday, September 6, 2011

.NET Web Deploy options

What options are there to deploy .NET applications to a server farm? Unless you're at a small web shop, you've likely never had to encounter this question. But this last month, it was this very question that I began to ponder as I began a rotation to a different group whose responsibilities include managing builds for the weekly release and the deployment to a web farm.

So what options are there? At my previous job, the code deployments were a manual process where the IT group would run an MSI file we generated during the build and use this to deploy to the .NET code to the web and application servers. As the code was being deployed, SQL scripts would be executed via a custom tool designed to execute the scripts on multiple databases at once to ease in this step of the deployment and to better record the errors.

But is a manual process the only way to go? Certainly not. One option is to utilize Windows Group Policy to remotely install an MSI containing the updated code. While developers may not be familiar with this functionality, IT staff members will likely have used this before to manage the software on desktops or servers remotely.

Another option is to utilize Microsoft's Web Deploy Tool to create deployment packages to push out to code to other servers. This tool can take a snapshot of a website on one server and replicate it to another, or identify changes to a server and replicate them to another server. Deploying these changes is still a manual process, but the Web Deploy tool is a powerful tool that can make the deployment process easier.

Perhaps the most intriguing option out there is Microsoft's Web Farm Framework. This tool can work with the Web Deploy tool or an MSI to automatically handle the deployment to a farm of servers. According to Scott Gu's article on the tool, the Web Farm Framework is an IIS extension that is installed on each server in the farm. One server is identified as the 'Primary' server. Any changes made to this server will be replicated to the other servers in the farm, one at a time in order to keep the entire farm operational.

The Web Farm Framework makes deployments easy, but as with many tools, there are tradeoffs. Deployments will take longer as only one server is pulled from the farm at a time. Because of this strategy, all but one server can respond to requests during the deployment, yet the servers will be on different versions of the code. And what if there is a central database that the web farm utilizes that must be updated? When should the database be updated?

What's the best option for deploying .NET code to a Server Farm? It depends on your situation.

If you have a strong IT staff, perhaps they can administer the Web Farm using Windows Group Policy and MSI's that are created during the build process.

If the IT staff is not familiar with Windows Group Policy, perhaps Web Farm Framework is worthwhile option, especially if the system cannot be taken down during an upgrade.

If you have the spare development staff, your best option might be to build your own tools. This requires a group of developers with an understanding of how the system works as a whole, but with the effort, you can build yourself a tool-set geared directly towards your server farm.