January 2006 - Posts

Configuring a secure domain account for ASP.NET on Windows 2000
26 January 2006 18:01

I recently had to enable the ASP.NET account on a Windows 2000 machine to use a domain account so we could use NT Authentication to the SQL backend and the implementation of the domain account had to be secure. The hardest bit was securing the account, I wanted to give the account as few privileges as possible and make sure the account details could not be easily compromised.

It took me a little while to gather the information I needed so I’ve pulled it together below so as to help anyone else faced with this task. The end result is that the asp.net domain account has minimal privileges on the IIS server and SQL server and the account details are encrypted and stored in the registry.

The encryption of the account details is handled by aspnet_setrep.exe and the tool is described here. Its worth mentioning that the utility can be used for encrypting data in other configuration sections.

The steps to a secure world are:

IIS 

Enable anonymous access and integrated windows authentication.

Config Files

Machine.config

Amend the processModel section to read:

userName="registry:HKLM\Software\AspNetProcess\ASPNET_SETREG,userName"
password="registry:HKLM\Software\AspNetProcess\ASPNET_SETREG,password"

Web.config

Turn off impersonation and add trusted connection.


Utilities

Copy aspnet_setrep.exe to the .net framework directory and then run the utility with the settings below.

aspnet_setreg.exe -k:\Software\AspNetProcess -u:<DOMAIN\ACCOUNT> -p:<PASSWORD>

Security

1) Give the domain account permission to read the registry keys created.
2) Give the domain account the following file permissions

C:\%WINDIR%\Microsoft.NET\Framework\<VERSION>Vxxxxx\Temporary ASP.NET Files\  - Full Control
C:\%WINDIR%\temp\ - Read/Write/Delete
Application folder - Read 
%installroot% hierarchy(C:\WINNT\Microsoft.Net\Framework\v1.0.3705) - Read
C:\inetpub\wwwroot (or the path that thedefault Web site points to) - Read
C:\%WINDIR%\system32 - Read
C:\%WINDIR%\assembly - Read - This is the global assembly cache. You cannot directly use Windows Explorer to edit ACLs for this folder. Instead, use a command Windows and run the following command:cacls %windir%\assembly /e /t /p domain\useraccount:

3) Grant the domain account access to the appropriate databases on the SQL server.
by ACALVETT | with no comments
Filed under: ,
A performance analysis example
15 January 2006 17:53

Last week i was dragged kicking and screaming away from my allocated SQL 2005 days to spend 2 days diagnosing performance problems on one of the firms Systems and write a report.

Due to the sensitive nature of the data on the system it has been managed by another team and this was the first time i had looked at it. I thought i'd share my thought process to identifying the problem on the server and reference tools i used. Its the first iteration of the review and once my recommendations are implemented there will be another review to see what else may need dealing with. Please note however i have not included every single step i took otherwise i'd be writing a novel!

Scenario

The users of the system have been reporting intermitant time outs occuring in the front end application. Current system administrators have noted periods of high cpu usage. The server is Windows 2000 SP4 running SQL 2000 SP3a with 2 physical processors, hyperthreading enabled, 2gb memory, SAN attached (EVA 5000).

Analysis


The first port of call was to review the event logs and sql server logs for any errors that may indicate what is happening. These logs revealed nothing. Next port of call was to connect via Query Analyser and see what was going on. A quick look at current activity showed nothing much going on, so i did the standard SELECT * FROM SYSPROCESSES. Now this revealed that 80% of the connected spids last wait times had been for a latch and spefically the waitresource was 2:3:69 or 2:1:24.


This waitresource translates as follows first number = Db ID, in this case tempdb. second number = filegroup and 3rd number is the page.
So, this made me suspicious and i moved on. Next thing, we have a timeout at the front end so what is the server waiting for? To find this out i created the track_waitstats and get_waitstats procedures on the server and ran the track_waitstats for 8 hours with 5 minute samples. At the same time i kicked off a server side trace and performance monitor with all my standard counters and left this running for 24hrs.

 

One last thing to do was take a look at how SQL was using its memory. For this i used DBCC MEMORYSTATUS and DBCC MEMUSAGE. This did not reveal anything alarming but the DBCC MEMUSAGE did show that a log table was the top buffer cache user so i noted this and i would later suggest the table be reviewed and archived as appropriate.

 

The next day it was time to start reviewing the information i had gathered. I loaded up the trace with my trusty trace analysis tool which takes all the pain out of working with the trace. Within 30 minutes the tool had analysed the trace, loaded it into a normalised database and presented me with a summary report with the most interesting information. Alot of the time i don't need to go any deeper than the summary report, although in a small number of cases you do have to and then its a case of querying the normalised database to extract more information and in very rare cases going back to the trace (painful!).

 

The first thing i looked at was the wait statistics i captured using track_waitstats. This gave me the key to the problem and incdicated that the server spent 45% of its time waiting for latches! The other most significant wait @ 32% was for cxpackets which relate to parallelism.  Now with latching in my head i started thinking IO bottleneck but a little voice said, "unlikely, you are attached to a high performance SAN". So, i went to review my performance counters and specifically the Average and Current disk queue lengths inline with disk read & writes. Nothing! Queue lengths were negligable and read writes were nothing to boast about. So what next? Well, i need to know where the latching is occuring so i set up a loop to capture the output of sysprocesses for 45 minutes. Now this was interesting, most of the waiting is occuring in tempdb! Ahar! Everything now points to tempdb contention. For a moment i thought to myself its classic contention and follow Microsoft article about it. Never that easy though! I was not exhibiting waitresources of 2:1:1 or 2:1:3. 

 

So, my wait resources are primarily 2:3:69. What is this? So i delve into the page to take a look. To do this i used DBCC PAGE to find out whats on the page and what object it belongs to. Both the pages being flagged belonged to SYSINDEXES in tempdb. The alarm bells are now ringing, the contention is in tempdb around sysindexes. Probably some dodgy code so back to the summary results of my trace and lets take a look at the top queries by CPU, READS & WRITES.  Voila! There it is. There are 2 queries that consume 40% of all resouce requested by SQL on the box.

 

So tuning time. The primary problem was that one of the peices of code was doing a SELECT * INTO #TBL from badly_written_view. To the best of my understanding its was actually this that was causing the latch contention in tempdb. I believe that when you do select * into its holding latches around the appropriate tables including sysindexes but for the duration of the transaction which is up to 3.5mins in this case. So i have removed the select * into and changed it to create #table followed by insert into. I then spent the next 5 hours optimising the code so i could send it back to the developers. I did not have to optimise the code but i was so horrified by the code i saw and a little part of me wanted to say to them "And thats how you do it". I managed to half the execution times on both bits of code but there was still room for improvement but that was going to take to much time as i was not not familiar enough with the dataset and my optimising was rusty.

 

The developers now have my recommendations and new code for review, hopefully changes will be implemented in the next week and i can confirm my belief regarding select * into.  Either way i`ll be doing another round of reviewing.

 

I've decided to stop here for the blog but a number of other recommendations were made which i've listed below. Every iteration of a performance review is different and other tools i have not mentioned are used but i hope you find this article gives you an insight into tuning and that its links are useful.

 

1) Increase tempdb files to match the number of processors. (Best practice)

2) Reduce degree of parallelism to n - 1 where n is the number of physical processors.

3) Review archive table.

 

Who knows, the next review may turn up a whole new world of pain or confirm the server is now running in a satisfactory state! One thing i can say for sure, the way i approach the problem and the tools i use next time will be similar but definately not the same.

by ACALVETT | with no comments
Filed under: , ,
SQL 2005 - Maintenance Plans
03 January 2006 18:24

I made a decision that to really get things going and identify "trouble spots" that i would continue my quick win approach.

So basically i`m working through installing and configuring our test SQL 2005 box following our SQL 2000 install instructions. Through out this approach i`m documenting and making necessary changes so i can have first drafts of install docs which i`m sure will evolve into excellent documents by the end of the project :D

So, having done the basic install which i talked about previously i decided lets tackle maintenance plans as there should not be to many surprises here.........

I have got to say that the new maintenance plans are far more flexible than ever before with alot of added functionality and over all i'd say its a job well done. However the new maintenance plans have inflicted much pain for me.

The Wizard

When i saw the maintenance plan wizard i thought to myself 'Hello old friend' and started to prepare a generic plan but through out i felt something was missing and then i clicked. I was only able to create a schedule to execute the plan at the end of the wizard and there was only 1! Surely there must be 1 for each set of tasks like SQL 2000? ie 1 for backups, one for dbcc's, one from transaction logs etc! No, just 1 schedule for what was created in the maintenance plan wizard!

Now i feel personally that this devalues the wizard significantly as we will have to run it multiple times for each item requiring a different schedule so we may as well use the maintenance plan designer!

Your probably thinking, use the designer, its more flexible and wizards are for wimps! Well, i do prefer the desginer but we will deploy to 25 countries and generally each country will do their installs from our documentation and have little or no SQL experience so wizards are good for them. Today they can follow 1 wizard and hey presto their SQL Server is being backup up, optimized etc.

Logging

Having got quite frustrated by the issue with the wizard but having accepted it i continued on. I was looking at the reporting options and then the real killer hit! The option to log the maintenance plan execution to a remote server was missing and a big black cloud arrived over my desk! Searching around and checking my books confirmed it had been removed and there appears to be no work around.

The loss of remote logging is a real blow because our 150 SQL servers log all their maintenance plan activity to one central MSDB. From this central location then run reports on which SQL servers have not run maintenance plans, who is reporting errors, which databases are not being backed up and so on. Now with the removal of this logging option our inhouse centralised solution will not work out of the box!

I've rattled around the maintenance plans and even imported them into SSIS to try and combat the problem. The issue with using SSIS is that although i can add multiple log destinations i lose all the flexibility. So right now i've not come up with a solution and have put this on my significant issues list. Part of the problem of coming up with the solution is that there are so many ways to solve it in 2005 and more than 1 technology available to do it with that i must remember to keep it simple and reliable. Since a rewrite is pretty much inevitable though i am considering expanding the new consolidation process to include other logs generated by SQL.

Maintenance Cleanup Task

I'd created the transaction log backup and set it to create subdirectories but now there is no option to delete the old backups in the transaction log task. This was quickly identified as something that has been moved to the maintenance cleanup task. The problem with this is that the maintenance cleanup task is only available in the maintenance plan designer which pretty much put the final nail in the coffin for using the wizard!

Next and most importantly, my transaction log backup is creating sub directories. However the maintenance cleanup task does not deal with sub directories!!! I`m not sure why Microsoft have removed this functionality but it seems crazy to offer the creation of files in sub directories without the ability to maintain the files in them!

To work around the problem you have to create a task for each subdirectory (not very dynamic...) or write your own script. I`ll be knocking up a script and post it in my next blog but don't expect anything elegant!  ;)

Summary

I still believe the maintenance plans have improved overall and especially the rebuild and reorganise index tasks. We don't use all the maintenance plans functionality on all servers because its more like taking a sledge hammer to crack a nut and some things are best done through scripting (for example analysing fragmentation on large tables and taking appropriate action based on the results).

The 2005 maintenance plans have proven more of a problem than i thought they would but is that not always the way? At the end of the day we will come up with better maintenance plans although they are not going to be as straight forward to create because for us, the Wizard is dead.

Until next time!